Bug 1206560 - Show the site favicon in XUL notifications. r=jaws
MozReview-Commit-ID: FMVYO1DCFDm
--- a/browser/base/content/test/alerts/browser_notification_close.js
+++ b/browser/base/content/test/alerts/browser_notification_close.js
@@ -1,17 +1,30 @@
"use strict";
+const {PlacesTestUtils} =
+ Cu.import("resource://testing-common/PlacesTestUtils.jsm", {});
+
let tab;
let notification;
let notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
add_task(function* test_notificationClose() {
let pm = Services.perms;
- pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
+ let notificationURI = makeURI(notificationURL);
+ pm.add(notificationURI, "desktop-notification", pm.ALLOW_ACTION);
+
+ yield PlacesTestUtils.addVisits(notificationURI);
+ let faviconURI = yield new Promise(resolve => {
+ let faviconURI = makeURI("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC");
+ PlacesUtils.favicons.setAndFetchFaviconForPage(notificationURI, faviconURI,
+ true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
+ (faviconURI, iconSize, iconData, mimeType) => resolve(faviconURI),
+ Services.scriptSecurityManager.getSystemPrincipal());
+ });
yield BrowserTestUtils.withNewTab({
gBrowser,
url: notificationURL
}, function* dummyTabTask(aBrowser) {
let win = aBrowser.contentWindow.wrappedJSObject;
notification = win.showNotification2();
yield BrowserTestUtils.waitForEvent(notification, "show");
@@ -24,16 +37,18 @@ add_task(function* test_notificationClos
notification.close();
return;
}
let alertTitleLabel = alertWindow.document.getElementById("alertTitleLabel");
is(alertTitleLabel.value, "Test title", "Title text of notification should be present");
let alertTextLabel = alertWindow.document.getElementById("alertTextLabel");
is(alertTextLabel.textContent, "Test body", "Body text of notification should be present");
+ let alertIcon = alertWindow.document.getElementById("alertIcon");
+ is(alertIcon.src, faviconURI.spec, "Icon of notification should be present");
let alertCloseButton = alertWindow.document.querySelector(".alertCloseButton");
is(alertCloseButton.localName, "toolbarbutton", "close button found");
let promiseBeforeUnloadEvent =
BrowserTestUtils.waitForEvent(alertWindow, "beforeunload");
let closedTime = alertWindow.Date.now();
alertCloseButton.click();
info("Clicked on close button");
--- a/toolkit/components/alerts/nsXULAlerts.cpp
+++ b/toolkit/components/alerts/nsXULAlerts.cpp
@@ -43,17 +43,17 @@ nsXULAlertObserver::Observe(nsISupports*
nsresult rv = NS_OK;
if (mObserver) {
rv = mObserver->Observe(aSubject, aTopic, aData);
}
return rv;
}
-NS_IMPL_ISUPPORTS(nsXULAlerts, nsIAlertsService, nsIAlertsDoNotDisturb)
+NS_IMPL_ISUPPORTS(nsXULAlerts, nsIAlertsService, nsIAlertsDoNotDisturb, nsIAlertsIconURI)
/* static */ already_AddRefed<nsXULAlerts>
nsXULAlerts::GetInstance()
{
if (!gXULAlerts) {
gXULAlerts = new nsXULAlerts();
ClearOnShutdown(&gXULAlerts);
}
@@ -79,16 +79,24 @@ nsXULAlerts::ShowAlertNotification(const
NS_ENSURE_SUCCESS(rv, rv);
return ShowAlert(alert, aAlertListener);
}
NS_IMETHODIMP
nsXULAlerts::ShowAlert(nsIAlertNotification* aAlert,
nsIObserver* aAlertListener)
{
+ return ShowAlertWithIconURI(aAlert, aAlertListener, nullptr);
+}
+
+NS_IMETHODIMP
+nsXULAlerts::ShowAlertWithIconURI(nsIAlertNotification* aAlert,
+ nsIObserver* aAlertListener,
+ nsIURI* aIconURI)
+{
bool inPrivateBrowsing;
nsresult rv = aAlert->GetInPrivateBrowsing(&inPrivateBrowsing);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString cookie;
rv = aAlert->GetCookie(cookie);
NS_ENSURE_SUCCESS(rv, rv);
@@ -235,16 +243,27 @@ nsXULAlerts::ShowAlert(nsIAlertNotificat
// 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);
scriptableAlertSource->SetData(source);
rv = argsArray->AppendElement(scriptableAlertSource);
NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsISupportsCString> scriptableIconURL (do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID));
+ NS_ENSURE_TRUE(scriptableIconURL, NS_ERROR_FAILURE);
+ if (aIconURI) {
+ nsAutoCString iconURL;
+ rv = aIconURI->GetSpec(iconURL);
+ NS_ENSURE_SUCCESS(rv, rv);
+ scriptableIconURL->SetData(iconURL);
+ }
+ rv = argsArray->AppendElement(scriptableIconURL);
+ NS_ENSURE_SUCCESS(rv, rv);
+
nsCOMPtr<mozIDOMWindowProxy> newWindow;
nsAutoCString features("chrome,dialog=yes,titlebar=no,popup=yes");
if (inPrivateBrowsing) {
features.AppendLiteral(",private");
}
rv = wwatch->OpenWindow(nullptr, ALERT_CHROME_URL, "_blank", features.get(),
argsArray, getter_AddRefs(newWindow));
NS_ENSURE_SUCCESS(rv, rv);
--- a/toolkit/components/alerts/nsXULAlerts.h
+++ b/toolkit/components/alerts/nsXULAlerts.h
@@ -8,20 +8,22 @@
#include "nsHashKeys.h"
#include "nsInterfaceHashtable.h"
#include "mozIDOMWindow.h"
#include "nsIObserver.h"
class nsXULAlerts : public nsIAlertsService,
- public nsIAlertsDoNotDisturb
+ public nsIAlertsDoNotDisturb,
+ public nsIAlertsIconURI
{
friend class nsXULAlertObserver;
public:
+ NS_DECL_NSIALERTSICONURI
NS_DECL_NSIALERTSDONOTDISTURB
NS_DECL_NSIALERTSSERVICE
NS_DECL_ISUPPORTS
nsXULAlerts()
{
}
--- a/toolkit/components/alerts/resources/content/alert.css
+++ b/toolkit/components/alerts/resources/content/alert.css
@@ -8,20 +8,26 @@
animation-name: alert-animation;
}
#alertBox[animate]:not([clicked]):not([closing]):hover {
animation-play-state: paused;
}
#alertBox:not([hasOrigin]) > box > #alertTextBox > #alertFooter,
+#alertBox:not([hasIcon]) > box > #alertIcon,
#alertImage:not([src]) {
display: none;
}
+#alertTitleBox {
+ -moz-box-pack: center;
+ -moz-box-align: center;
+}
+
.alertText {
white-space: pre-wrap;
}
@keyframes alert-animation {
to {
visibility: hidden;
}
--- a/toolkit/components/alerts/resources/content/alert.js
+++ b/toolkit/components/alerts/resources/content/alert.js
@@ -32,19 +32,29 @@ function prefillAlertInfo() {
// arguments[3] --> is the text clickable?
// arguments[4] --> the alert cookie to be passed back to the listener
// arguments[5] --> the alert origin reported by the look and feel
// arguments[6] --> bidi
// arguments[7] --> lang
// arguments[8] --> replaced alert window (nsIDOMWindow)
// arguments[9] --> an optional callback listener (nsIObserver)
// arguments[10] -> the nsIURI.hostPort of the origin, optional
+ // arguments[11] -> the alert icon URL, optional
switch (window.arguments.length) {
default:
+ case 12: {
+ if (window.arguments[11]) {
+ let alertBox = document.getElementById("alertBox");
+ alertBox.setAttribute("hasIcon", true);
+
+ let icon = document.getElementById("alertIcon");
+ icon.src = window.arguments[11];
+ }
+ }
case 11: {
if (window.arguments[10]) {
let alertBox = document.getElementById("alertBox");
alertBox.setAttribute("hasOrigin", true);
let hostPort = window.arguments[10];
const ALERT_BUNDLE = Services.strings.createBundle(
"chrome://alerts/locale/alert.properties");
--- a/toolkit/components/alerts/resources/content/alert.xul
+++ b/toolkit/components/alerts/resources/content/alert.xul
@@ -20,16 +20,17 @@
onload="onAlertLoad();"
onclick="onAlertClick();"
onbeforeunload="onAlertBeforeUnload();">
<script type="application/javascript" src="chrome://global/content/alerts/alert.js"/>
<vbox id="alertBox" class="alertBox">
<box id="alertTitleBox">
+ <image id="alertIcon"/>
<label id="alertTitleLabel" class="alertTitle plain" crop="end"/>
<vbox class="alertCloseBox">
<toolbarbutton class="alertCloseButton close-icon"
tooltiptext="&closeAlert.tooltip;"
onclick="event.stopPropagation();"
oncommand="onAlertClose();"/>
</vbox>
</box>
--- a/toolkit/themes/shared/alert-common.css
+++ b/toolkit/themes/shared/alert-common.css
@@ -48,16 +48,32 @@
}
@keyframes alert-closing-animation {
to {
opacity: 0;
}
}
+#alertIcon {
+ margin-top: 6px;
+ margin-inline-start: 8px;
+ margin-inline-end: 0;
+ margin-bottom: 0;
+ width: 16px;
+ min-height: 16px;
+ max-height: 16px;
+}
+
+@media (resolution: 2dppx) {
+ #alertIcon {
+ image-rendering: -moz-crisp-edges;
+ }
+}
+
#alertImage {
width: 80px;
height: 80px;
max-width: 80px;
max-height: 80px;
object-fit: scale-down;
margin: 0 7px 7px;
}