--- a/browser/components/shell/nsWindowsShellService.cpp
+++ b/browser/components/shell/nsWindowsShellService.cpp
@@ -4,22 +4,20 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsWindowsShellService.h"
#include "BinaryPath.h"
#include "city.h"
#include "imgIContainer.h"
#include "imgIRequest.h"
-#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
#include "nsIContent.h"
#include "nsIDOMElement.h"
#include "nsIImageLoadingContent.h"
-#include "nsIOutputStream.h"
#include "nsIPrefService.h"
#include "nsIPrefLocalizedString.h"
#include "nsIServiceManager.h"
#include "nsIStringBundle.h"
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "nsShellService.h"
#include "nsIProcess.h"
@@ -41,16 +39,17 @@
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600
#define INITGUID
#undef NTDDI_VERSION
#define NTDDI_VERSION NTDDI_WIN8
// Needed for access to IApplicationActivationManager
#include <shlobj.h>
+#include "WinUtils.h"
#include <mbstring.h>
#include <shlwapi.h>
#include <lm.h>
#undef ACCESS_READ
#ifndef MAX_BUF
@@ -62,17 +61,17 @@
#define REG_FAILED(val) \
(val != ERROR_SUCCESS)
#define APP_REG_NAME_BASE L"Firefox-"
using mozilla::IsWin8OrLater;
using namespace mozilla;
-using namespace mozilla::gfx;
+using namespace mozilla::widget;
NS_IMPL_ISUPPORTS(nsWindowsShellService, nsIShellService)
static nsresult
OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
{
const nsString &flatName = PromiseFlatString(aKeyName);
@@ -480,105 +479,16 @@ nsWindowsShellService::SetDefaultBrowser
// Reset the number of times the dialog should be shown
// before it is silenced.
(void) prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0);
}
return rv;
}
-static nsresult
-WriteBitmap(nsIFile* aFile, imgIContainer* aImage)
-{
- nsresult rv;
-
- RefPtr<SourceSurface> surface =
- aImage->GetFrame(imgIContainer::FRAME_FIRST,
- imgIContainer::FLAG_SYNC_DECODE);
- NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
-
- // For either of the following formats we want to set the biBitCount member
- // of the BITMAPINFOHEADER struct to 32, below. For that value the bitmap
- // format defines that the A8/X8 WORDs in the bitmap byte stream be ignored
- // for the BI_RGB value we use for the biCompression member.
- MOZ_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8A8 ||
- surface->GetFormat() == SurfaceFormat::B8G8R8X8);
-
- RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
- NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
-
- int32_t width = dataSurface->GetSize().width;
- int32_t height = dataSurface->GetSize().height;
- int32_t bytesPerPixel = 4 * sizeof(uint8_t);
- uint32_t bytesPerRow = bytesPerPixel * width;
-
- // initialize these bitmap structs which we will later
- // serialize directly to the head of the bitmap file
- BITMAPINFOHEADER bmi;
- bmi.biSize = sizeof(BITMAPINFOHEADER);
- bmi.biWidth = width;
- bmi.biHeight = height;
- bmi.biPlanes = 1;
- bmi.biBitCount = (WORD)bytesPerPixel*8;
- bmi.biCompression = BI_RGB;
- bmi.biSizeImage = bytesPerRow * height;
- bmi.biXPelsPerMeter = 0;
- bmi.biYPelsPerMeter = 0;
- bmi.biClrUsed = 0;
- bmi.biClrImportant = 0;
-
- BITMAPFILEHEADER bf;
- bf.bfType = 0x4D42; // 'BM'
- bf.bfReserved1 = 0;
- bf.bfReserved2 = 0;
- bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
- bf.bfSize = bf.bfOffBits + bmi.biSizeImage;
-
- // get a file output stream
- nsCOMPtr<nsIOutputStream> stream;
- rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile);
- NS_ENSURE_SUCCESS(rv, rv);
-
- DataSourceSurface::MappedSurface map;
- if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) {
- return NS_ERROR_FAILURE;
- }
-
- // write the bitmap headers and rgb pixel data to the file
- rv = NS_ERROR_FAILURE;
- if (stream) {
- uint32_t written;
- stream->Write((const char*)&bf, sizeof(BITMAPFILEHEADER), &written);
- if (written == sizeof(BITMAPFILEHEADER)) {
- stream->Write((const char*)&bmi, sizeof(BITMAPINFOHEADER), &written);
- if (written == sizeof(BITMAPINFOHEADER)) {
- // write out the image data backwards because the desktop won't
- // show bitmaps with negative heights for top-to-bottom
- uint32_t i = map.mStride * height;
- do {
- i -= map.mStride;
- stream->Write(((const char*)map.mData) + i, bytesPerRow, &written);
- if (written == bytesPerRow) {
- rv = NS_OK;
- } else {
- rv = NS_ERROR_FAILURE;
- break;
- }
- } while (i != 0);
- }
- }
-
- stream->Close();
- }
-
- dataSurface->Unmap();
-
- return rv;
-}
-
NS_IMETHODIMP
nsWindowsShellService::SetDesktopBackground(nsIDOMElement* aElement,
int32_t aPosition,
const nsACString& aImageName)
{
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
if (!content || !content->IsHTMLElement(nsGkAtoms::img)) {
// XXX write background loading stuff!
@@ -629,17 +539,17 @@ nsWindowsShellService::SetDesktopBackgro
rv = file->Append(fileLeafName);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString path;
rv = file->GetPath(path);
NS_ENSURE_SUCCESS(rv, rv);
// write the bitmap to a file in the profile directory
- rv = WriteBitmap(file, container);
+ rv = WinUtils::WriteBitmap(file, container);
// if the file was written successfully, set it as the system wallpaper
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -320,16 +320,17 @@ if CONFIG['OS_ARCH'] == 'WINNT':
'secur32',
'sensorsapi',
'portabledeviceguids',
'wininet',
'wbemuuid',
'wintrust',
'wtsapi32',
'locationapi',
+ 'runtimeobject',
'sapi',
'dxguid',
]
if CONFIG['ACCESSIBILITY']:
OS_LIBS += [
'oleacc',
]
new file mode 100644
--- /dev/null
+++ b/widget/windows/ToastNotification.cpp
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sts=2 sw=2 et cin: */
+/* 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 "ToastNotification.h"
+
+#include "mozilla/WindowsVersion.h"
+#include "nsComponentManagerUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIObserverService.h"
+#include "nsString.h"
+#include "nsThreadUtils.h"
+
+#include "ToastNotificationHandler.h"
+
+namespace mozilla {
+namespace widget {
+
+NS_IMPL_ISUPPORTS(ToastNotification, nsIAlertsService, nsIObserver, nsISupportsWeakReference)
+
+ToastNotification::ToastNotification()
+= default;
+
+ToastNotification::~ToastNotification()
+= default;
+
+nsresult
+ToastNotification::Init()
+{
+ if (!IsWin8OrLater()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ nsresult rv = NS_NewNamedThread("ToastBgThread", getter_AddRefs(mBackgroundThread));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsCOMPtr<nsIObserverService> obsServ =
+ do_GetService("@mozilla.org/observer-service;1");
+ if (obsServ) {
+ obsServ->AddObserver(this, "quit-application", true);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+ToastNotification::BackgroundDispatch(nsIRunnable* runnable)
+{
+ return mBackgroundThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
+}
+
+NS_IMETHODIMP
+ToastNotification::Observe(nsISupports *aSubject, const char *aTopic,
+ const char16_t *aData) {
+ // Got quit-application
+ // The handlers destructors will do the right thing (de-register with Windows).
+ mActiveHandlers.Clear();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ToastNotification::ShowAlertNotification(const nsAString & aImageUrl,
+ const nsAString & aAlertTitle,
+ const nsAString & aAlertText,
+ bool aAlertTextClickable,
+ const nsAString & aAlertCookie,
+ nsIObserver * aAlertListener,
+ const nsAString & aAlertName,
+ const nsAString & aBidi,
+ const nsAString & aLang,
+ const nsAString & aData,
+ nsIPrincipal * aPrincipal,
+ bool aInPrivateBrowsing,
+ bool aRequireInteraction)
+{
+ nsCOMPtr<nsIAlertNotification> alert =
+ do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
+ if (NS_WARN_IF(!alert)) {
+ return NS_ERROR_FAILURE;
+ }
+ nsresult rv = alert->Init(aAlertName, aImageUrl, aAlertTitle,
+ aAlertText, aAlertTextClickable,
+ aAlertCookie, aBidi, aLang, aData,
+ aPrincipal, aInPrivateBrowsing,
+ aRequireInteraction);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ return ShowAlert(alert, aAlertListener);
+}
+
+NS_IMETHODIMP
+ToastNotification::ShowPersistentNotification(const nsAString& aPersistentData,
+ nsIAlertNotification* aAlert,
+ nsIObserver* aAlertListener)
+{
+ return ShowAlert(aAlert, aAlertListener);
+}
+
+NS_IMETHODIMP
+ToastNotification::ShowAlert(nsIAlertNotification* aAlert,
+ nsIObserver* aAlertListener)
+{
+ if (NS_WARN_IF(!aAlert)) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ nsAutoString cookie;
+ nsresult rv = aAlert->GetCookie(cookie);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsAutoString name;
+ rv = aAlert->GetName(name);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsAutoString title;
+ rv = aAlert->GetTitle(title);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsAutoString text;
+ rv = aAlert->GetText(text);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ bool textClickable;
+ rv = aAlert->GetTextClickable(&textClickable);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ RefPtr<ToastNotificationHandler> handler =
+ new ToastNotificationHandler(this, aAlertListener, name, cookie, title,
+ text, textClickable);
+ mActiveHandlers.Put(name, handler);
+
+ rv = handler->InitAlertAsync(aAlert);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ mActiveHandlers.Remove(name);
+ return rv;
+ }
+
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ToastNotification::CloseAlert(const nsAString& aAlertName,
+ nsIPrincipal* aPrincipal)
+{
+ RefPtr<ToastNotificationHandler> handler;
+ if (NS_WARN_IF(!mActiveHandlers.Get(aAlertName, getter_AddRefs(handler)))) {
+ return NS_OK;
+ }
+ mActiveHandlers.Remove(aAlertName);
+ return NS_OK;
+}
+
+bool
+ToastNotification::IsActiveHandler(const nsAString& aAlertName,
+ ToastNotificationHandler* aHandler)
+{
+ RefPtr<ToastNotificationHandler> handler;
+ if (NS_WARN_IF(!mActiveHandlers.Get(aAlertName, getter_AddRefs(handler)))) {
+ return false;
+ }
+ return handler == aHandler;
+}
+
+void
+ToastNotification::RemoveHandler(const nsAString& aAlertName,
+ ToastNotificationHandler* aHandler)
+{
+ // The alert may have been replaced; only remove it from the active
+ // handlers map if it's the same.
+ if (IsActiveHandler(aAlertName, aHandler)) {
+ // Terrible things happen if the destructor of a handler is called inside
+ // the hashtable .Remove() method. Wait until we have returned from there.
+ RefPtr<ToastNotificationHandler> kungFuDeathGrip(aHandler);
+ mActiveHandlers.Remove(aAlertName);
+ }
+}
+
+} // namespace widget
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/widget/windows/ToastNotification.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef ToastNotification_h__
+#define ToastNotification_h__
+
+#include "nsIAlertsService.h"
+#include "nsIObserver.h"
+#include "nsIThread.h"
+#include "nsRefPtrHashtable.h"
+#include "nsWeakReference.h"
+
+namespace mozilla {
+namespace widget {
+
+class ToastNotificationHandler;
+
+class ToastNotification final : public nsIAlertsService,
+ public nsIObserver,
+ public nsSupportsWeakReference
+{
+public:
+ NS_DECL_NSIALERTSSERVICE
+ NS_DECL_NSIOBSERVER
+ NS_DECL_ISUPPORTS
+
+ ToastNotification();
+
+ nsresult Init();
+
+ bool IsActiveHandler(const nsAString& aAlertName,
+ ToastNotificationHandler* aHandler);
+ void RemoveHandler(const nsAString& aAlertName,
+ ToastNotificationHandler* aHandler);
+
+ nsresult BackgroundDispatch(nsIRunnable* runnable);
+
+protected:
+ virtual ~ToastNotification();
+
+ nsRefPtrHashtable<nsStringHashKey, ToastNotificationHandler> mActiveHandlers;
+
+ nsCOMPtr<nsIThread> mBackgroundThread;
+};
+
+} // widget
+} // mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/widget/windows/ToastNotificationHandler.cpp
@@ -0,0 +1,510 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sts=2 sw=2 et cin: */
+/* 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 "ToastNotificationHandler.h"
+
+#include "imgIRequest.h"
+#include "mozilla/gfx/2D.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsIURI.h"
+#include "nsIUUIDGenerator.h"
+#include "nsNetUtil.h"
+#include "nsProxyRelease.h"
+#include "WinTaskbar.h"
+#include "WinUtils.h"
+
+#include "ToastNotification.h"
+
+namespace mozilla {
+namespace widget {
+
+typedef ABI::Windows::Foundation::ITypedEventHandler<
+ ABI::Windows::UI::Notifications::ToastNotification*, IInspectable*>
+ ToastActivationHandler;
+typedef ABI::Windows::Foundation::ITypedEventHandler<
+ ABI::Windows::UI::Notifications::ToastNotification*,
+ ABI::Windows::UI::Notifications::ToastDismissedEventArgs*> ToastDismissedHandler;
+typedef ABI::Windows::Foundation::ITypedEventHandler<
+ ABI::Windows::UI::Notifications::ToastNotification*,
+ ABI::Windows::UI::Notifications::ToastFailedEventArgs*> ToastFailedHandler;
+
+using namespace ABI::Windows::Data::Xml::Dom;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::UI::Notifications;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace mozilla;
+
+NS_IMPL_ISUPPORTS(ToastNotificationHandler, nsIAlertNotificationImageListener)
+
+static bool
+SetNodeValueString(const nsAString& aString,
+ IXmlNode* node,
+ IXmlDocument* xml)
+{
+ ComPtr<IXmlText> inputText;
+ HRESULT hr;
+ HSTRING value = HStringReference(reinterpret_cast<const wchar_t*>(aString.BeginReading())).Get();
+
+ hr = xml->CreateTextNode(value, &inputText);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+ ComPtr<IXmlNode> inputTextNode;
+ hr = inputText.As(&inputTextNode);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+ ComPtr<IXmlNode> appendedChild;
+ hr = node->AppendChild(inputTextNode.Get(), &appendedChild);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+SetAttribute(IXmlElement* element, const nsAString& name, const nsAString& value) {
+ HSTRING nameStr = HStringReference(reinterpret_cast<const wchar_t*>(name.BeginReading())).Get();
+ HSTRING valueStr = HStringReference(reinterpret_cast<const wchar_t*>(value.BeginReading())).Get();
+ if (NS_WARN_IF(FAILED(element->SetAttribute(nameStr, valueStr)))) {
+ return false;
+ }
+ return true;
+}
+
+static bool
+AddActionNode(IXmlDocument* toastXml, IXmlNode* actionsNode, const nsAString& actionTitle, const nsAString& actionArgs) {
+ ComPtr<IXmlElement> action;
+ toastXml->CreateElement(HStringReference(L"action").Get(), &action);
+
+ HRESULT hr = SetAttribute(action.Get(), NS_LITERAL_STRING("content"), actionTitle);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+ hr = SetAttribute(action.Get(), NS_LITERAL_STRING("arguments"), actionArgs);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+ hr = SetAttribute(action.Get(), NS_LITERAL_STRING("placement"), NS_LITERAL_STRING("contextmenu"));
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ // Add <action> to <actions>
+ ComPtr<IXmlNode> actionNode;
+ hr = action.As(&actionNode);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ ComPtr<IXmlNode> appendedChild;
+ hr = actionsNode->AppendChild(actionNode.Get(), &appendedChild);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ return true;
+}
+
+static ComPtr<IToastNotificationManagerStatics>
+GetToastNotificationManagerStatics()
+{
+ ComPtr<IToastNotificationManagerStatics> toastNotificationManagerStatics;
+ HRESULT hr;
+ hr = GetActivationFactory(
+ HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(),
+ toastNotificationManagerStatics.GetAddressOf());
+ if (NS_WARN_IF(FAILED(hr))) {
+ return nullptr;
+ }
+
+ return toastNotificationManagerStatics;
+}
+
+ToastNotificationHandler::~ToastNotificationHandler()
+{
+ if (mImageRequest) {
+ mImageRequest->Cancel(NS_BINDING_ABORTED);
+ mImageRequest = nullptr;
+ }
+
+ if (mHasImage) {
+ mImageFile->Remove(false);
+ }
+
+ if (mNotification && mNotifier) {
+ mNotification->remove_Dismissed(mDismissedToken);
+ mNotification->remove_Activated(mActivatedToken);
+ mNotification->remove_Failed(mFailedToken);
+ mNotifier->Hide(mNotification.Get());
+ }
+}
+
+ComPtr<IXmlDocument>
+ToastNotificationHandler::InitializeXmlForTemplate(
+ ToastTemplateType templateType)
+{
+ ComPtr<IToastNotificationManagerStatics> toastNotificationManagerStatics =
+ GetToastNotificationManagerStatics();
+
+ ComPtr<IXmlDocument> toastXml;
+ toastNotificationManagerStatics->GetTemplateContent(templateType, &toastXml);
+
+ return toastXml;
+}
+
+nsresult
+ToastNotificationHandler::InitAlertAsync(nsIAlertNotification* aAlert)
+{
+ return aAlert->LoadImage(/* aTimeout = */ 0, this, /* aUserData = */ nullptr,
+ getter_AddRefs(mImageRequest));
+}
+
+bool
+ToastNotificationHandler::ShowAlert()
+{
+ if (!mBackend->IsActiveHandler(mName, this)) {
+ return true;
+ }
+
+ ComPtr<IXmlDocument> toastXml =
+ InitializeXmlForTemplate(
+ !mHasImage ?
+ ToastTemplateType::ToastTemplateType_ToastText03 :
+ ToastTemplateType::ToastTemplateType_ToastImageAndText03);
+
+ if (!toastXml) {
+ return false;
+ }
+
+ HRESULT hr;
+
+ if (mHasImage) {
+ ComPtr<IXmlNodeList> toastImageElements;
+ hr = toastXml->GetElementsByTagName(HStringReference(L"image").Get(),
+ toastImageElements.GetAddressOf());
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+ ComPtr<IXmlNode> imageNode;
+ hr = toastImageElements->Item(0, &imageNode);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+ ComPtr<IXmlElement> image;
+ hr = imageNode.As(&image);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+ hr = SetAttribute(image.Get(), NS_LITERAL_STRING("src"), mImageUri);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+ }
+
+ ComPtr<IXmlNodeList> toastTextElements;
+ hr = toastXml->GetElementsByTagName(HStringReference(L"text").Get(),
+ toastTextElements.GetAddressOf());
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ ComPtr<IXmlNode> titleTextNodeRoot;
+ hr = toastTextElements->Item(0, &titleTextNodeRoot);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+ ComPtr<IXmlNode> msgTextNodeRoot;
+ hr = toastTextElements->Item(1, &msgTextNodeRoot);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ SetNodeValueString(mTitle, titleTextNodeRoot.Get(), toastXml.Get());
+ SetNodeValueString(mMsg, msgTextNodeRoot.Get(), toastXml.Get());
+
+ ComPtr<IXmlNodeList> toastElements;
+ hr = toastXml->GetElementsByTagName(HStringReference(L"toast").Get(),
+ toastElements.GetAddressOf());
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ ComPtr<IXmlNode> toastNodeRoot;
+ hr = toastElements->Item(0, &toastNodeRoot);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ ComPtr<IXmlElement> actions;
+ toastXml->CreateElement(HStringReference(L"actions").Get(), &actions);
+
+ ComPtr<IXmlNode> actionsNode;
+ hr = actions.As(&actionsNode);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ AddActionNode(toastXml.Get(), actionsNode.Get(), NS_LITERAL_STRING("Snooze"), NS_LITERAL_STRING("snooze=1"));
+ AddActionNode(toastXml.Get(), actionsNode.Get(), NS_LITERAL_STRING("Settings"), NS_LITERAL_STRING("settings=1"));
+
+ ComPtr<IXmlNode> appendedChild;
+ hr = toastNodeRoot->AppendChild(actionsNode.Get(), &appendedChild);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ return CreateWindowsNotificationFromXml(toastXml.Get());
+}
+
+bool
+ToastNotificationHandler::CreateWindowsNotificationFromXml(
+ IXmlDocument *aXml)
+{
+ ComPtr<IToastNotificationFactory> factory;
+ HRESULT hr;
+ hr = GetActivationFactory(
+ HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(),
+ factory.GetAddressOf());
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ hr = factory->CreateToastNotification(aXml, mNotification.GetAddressOf());
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ hr = mNotification->add_Activated(
+ Callback<ToastActivationHandler>(
+ this, &ToastNotificationHandler::OnActivate).Get(),
+ &mActivatedToken);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ hr = mNotification->add_Dismissed(
+ Callback<ToastDismissedHandler>(
+ this, &ToastNotificationHandler::OnDismiss).Get(),
+ &mDismissedToken);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ hr = mNotification->add_Failed(
+ Callback<ToastFailedHandler>(
+ this, &ToastNotificationHandler::OnFail).Get(),
+ &mFailedToken);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ ComPtr<IToastNotificationManagerStatics> toastNotificationManagerStatics =
+ GetToastNotificationManagerStatics();
+ if (!toastNotificationManagerStatics) {
+ return false;
+ }
+
+ nsAutoString uid;
+ if (!WinTaskbar::GetAppUserModelID(uid)) {
+ return false;
+ }
+
+ HSTRING uidStr = HStringReference(reinterpret_cast<const wchar_t*>(uid.BeginReading())).Get();
+ hr = toastNotificationManagerStatics->CreateToastNotifierWithId(uidStr, &mNotifier);
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ hr = mNotifier->Show(mNotification.Get());
+ if (NS_WARN_IF(FAILED(hr))) {
+ return false;
+ }
+
+ if (mAlertListener) {
+ mAlertListener->Observe(nullptr, "alertshow", mCookie.get());
+ }
+
+ return true;
+}
+
+HRESULT
+ToastNotificationHandler::OnActivate(IToastNotification *notification,
+ IInspectable *inspectable)
+{
+ ComPtr<IToastActivatedEventArgs> eventArgs;
+ inspectable->QueryInterface(__uuidof(IToastActivatedEventArgs), (void **)&eventArgs);
+
+ HSTRING args;
+ eventArgs->get_Arguments(&args);
+
+ if (mClickable && mAlertListener) {
+ mAlertListener->Observe(nullptr, "alertclickcallback", mCookie.get());
+ }
+ mBackend->RemoveHandler(mName, this);
+ return S_OK;
+}
+
+HRESULT
+ToastNotificationHandler::OnDismiss(IToastNotification *notification,
+ IToastDismissedEventArgs* aArgs)
+{
+ if (mAlertListener) {
+ mAlertListener->Observe(nullptr, "alertfinished", mCookie.get());
+ }
+ mBackend->RemoveHandler(mName, this);
+ return S_OK;
+}
+
+HRESULT
+ToastNotificationHandler::OnFail(IToastNotification *notification,
+ IToastFailedEventArgs* aArgs)
+{
+ if (mAlertListener) {
+ mAlertListener->Observe(nullptr, "alertfinished", mCookie.get());
+ }
+ mBackend->RemoveHandler(mName, this);
+ return S_OK;
+}
+
+nsresult
+ToastNotificationHandler::TryShowAlert()
+{
+ if (NS_WARN_IF(!ShowAlert())) {
+ mBackend->RemoveHandler(mName, this);
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+}
+NS_IMETHODIMP
+ToastNotificationHandler::OnImageMissing(nsISupports*)
+{
+ return TryShowAlert();
+}
+
+NS_IMETHODIMP
+ToastNotificationHandler::OnImageReady(nsISupports*, imgIRequest* aRequest)
+{
+ nsresult rv = AsyncSaveImage(aRequest);
+ if (NS_FAILED(rv)) {
+ return TryShowAlert();
+ }
+ return rv;
+}
+
+nsresult
+ToastNotificationHandler::AsyncSaveImage(imgIRequest* aRequest)
+{
+ nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR,
+ getter_AddRefs(mImageFile));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = mImageFile->Append(NS_LITERAL_STRING("notificationimages"));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = mImageFile->Create(nsIFile::DIRECTORY_TYPE, 0500);
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
+ return rv;
+ }
+
+ nsCOMPtr<nsIUUIDGenerator> idGen =
+ do_GetService("@mozilla.org/uuid-generator;1", &rv);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsID uuid;
+ rv = idGen->GenerateUUIDInPlace(&uuid);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ char uuidChars[NSID_LENGTH];
+ uuid.ToProvidedString(uuidChars);
+ // Remove the brackets at the beginning and ending of the generated UUID.
+ nsAutoCString uuidStr(Substring(uuidChars + 1, uuidChars + NSID_LENGTH - 2));
+ uuidStr.AppendLiteral(".bmp");
+ mImageFile->AppendNative(uuidStr);
+
+ nsCOMPtr<imgIContainer> imgContainer;
+ rv = aRequest->GetImage(getter_AddRefs(imgContainer));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsMainThreadPtrHandle<ToastNotificationHandler> self(
+ new nsMainThreadPtrHolder<ToastNotificationHandler>(
+ "ToastNotificationHandler", this));
+
+ nsCOMPtr<nsIFile> imageFile(mImageFile);
+ RefPtr<mozilla::gfx::SourceSurface> surface =
+ imgContainer->GetFrame(imgIContainer::FRAME_FIRST,
+ imgIContainer::FLAG_SYNC_DECODE);
+ nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+ "ToastNotificationHandler::AsyncWriteBitmap",
+ [self, imageFile, surface]() -> void {
+
+ nsresult rv;
+ if (!surface) {
+ rv = NS_ERROR_FAILURE;
+ } else {
+ rv = WinUtils::WriteBitmap(imageFile, surface);
+ }
+
+ nsCOMPtr<nsIRunnable> cbRunnable = NS_NewRunnableFunction(
+ "ToastNotificationHandler::AsyncWriteBitmapCb",
+ [self, rv]() -> void {
+ auto handler = const_cast<ToastNotificationHandler*>(self.get());
+ handler->OnWriteBitmapFinished(rv);
+ });
+
+ NS_DispatchToMainThread(cbRunnable);
+ });
+
+ return mBackend->BackgroundDispatch(r);
+}
+
+void
+ToastNotificationHandler::OnWriteBitmapFinished(nsresult rv)
+{
+ if (NS_SUCCEEDED(rv)) {
+ OnWriteBitmapSuccess();
+ }
+ TryShowAlert();
+}
+
+nsresult
+ToastNotificationHandler::OnWriteBitmapSuccess()
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIURI> fileURI;
+ rv = NS_NewFileURI(getter_AddRefs(fileURI), mImageFile);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsAutoCString uriStr;
+ rv = fileURI->GetSpec(uriStr);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ AppendUTF8toUTF16(uriStr, mImageUri);
+
+ mHasImage = true;
+
+ return NS_OK;
+}
+
+} // namespace widget
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/widget/windows/ToastNotificationHandler.h
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef ToastNotificationHandler_h__
+#define ToastNotificationHandler_h__
+
+#include <windows.ui.notifications.h>
+#include <windows.data.xml.dom.h>
+#include <wrl.h>
+#include "imgIContainer.h"
+#include "nsCOMPtr.h"
+#include "nsIAlertsService.h"
+#include "nsICancelable.h"
+#include "nsIFile.h"
+#include "nsString.h"
+
+namespace mozilla {
+namespace widget {
+
+class ToastNotification;
+
+class ToastNotificationHandler final : public nsIAlertNotificationImageListener
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIALERTNOTIFICATIONIMAGELISTENER
+
+ ToastNotificationHandler(ToastNotification* backend, nsIObserver* aAlertListener,
+ const nsAString& aName, const nsAString& aCookie,
+ const nsAString& aTitle, const nsAString& aMsg,
+ bool aClickable)
+ : mBackend(backend)
+ , mHasImage(false)
+ , mAlertListener(aAlertListener)
+ , mName(aName)
+ , mCookie(aCookie)
+ , mTitle(aTitle)
+ , mMsg(aMsg)
+ , mClickable(aClickable)
+ {
+ }
+
+ nsresult InitAlertAsync(nsIAlertNotification* aAlert);
+
+ void OnWriteBitmapFinished(nsresult rv);
+
+protected:
+ virtual ~ToastNotificationHandler();
+
+ typedef ABI::Windows::Data::Xml::Dom::IXmlDocument IXmlDocument;
+ typedef ABI::Windows::UI::Notifications::IToastNotifier
+ IToastNotifier;
+ typedef ABI::Windows::UI::Notifications::IToastNotification
+ IToastNotification;
+ typedef ABI::Windows::UI::Notifications::IToastDismissedEventArgs
+ IToastDismissedEventArgs;
+ typedef ABI::Windows::UI::Notifications::IToastFailedEventArgs
+ IToastFailedEventArgs;
+ typedef ABI::Windows::UI::Notifications::ToastTemplateType ToastTemplateType;
+
+ Microsoft::WRL::ComPtr<IToastNotification> mNotification;
+ Microsoft::WRL::ComPtr<IToastNotifier> mNotifier;
+
+ RefPtr<ToastNotification> mBackend;
+
+ nsCOMPtr<nsICancelable> mImageRequest;
+ nsCOMPtr<nsIFile> mImageFile;
+ nsString mImageUri;
+ bool mHasImage;
+
+ EventRegistrationToken mActivatedToken;
+ EventRegistrationToken mDismissedToken;
+ EventRegistrationToken mFailedToken;
+
+ nsCOMPtr<nsIObserver> mAlertListener;
+ nsString mName;
+ nsString mCookie;
+ nsString mTitle;
+ nsString mMsg;
+ bool mClickable;
+
+ nsresult TryShowAlert();
+ bool ShowAlert();
+ nsresult AsyncSaveImage(imgIRequest* aRequest);
+ nsresult OnWriteBitmapSuccess();
+
+ bool CreateWindowsNotificationFromXml(IXmlDocument* aToastXml);
+ Microsoft::WRL::ComPtr<IXmlDocument> InitializeXmlForTemplate(
+ ToastTemplateType templateType);
+
+ HRESULT OnActivate(IToastNotification *notification,
+ IInspectable *inspectable);
+ HRESULT OnDismiss(IToastNotification *notification,
+ IToastDismissedEventArgs* aArgs);
+ HRESULT OnFail(IToastNotification *notification,
+ IToastFailedEventArgs* aArgs);
+};
+
+} // widget
+} // mozilla
+
+#endif
--- a/widget/windows/WinUtils.cpp
+++ b/widget/windows/WinUtils.cpp
@@ -1771,16 +1771,113 @@ WinUtils::SetupKeyModifiersSequence(nsTA
/* static */
bool
WinUtils::ShouldHideScrollbars()
{
return false;
}
+/* static */
+nsresult
+WinUtils::WriteBitmap(nsIFile* aFile, imgIContainer* aImage)
+{
+ RefPtr<SourceSurface> surface =
+ aImage->GetFrame(imgIContainer::FRAME_FIRST,
+ imgIContainer::FLAG_SYNC_DECODE);
+ NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
+
+ return WriteBitmap(aFile, surface);
+}
+
+/* static */
+nsresult
+WinUtils::WriteBitmap(nsIFile* aFile, SourceSurface* surface)
+{
+ nsresult rv;
+
+ // For either of the following formats we want to set the biBitCount member
+ // of the BITMAPINFOHEADER struct to 32, below. For that value the bitmap
+ // format defines that the A8/X8 WORDs in the bitmap byte stream be ignored
+ // for the BI_RGB value we use for the biCompression member.
+ MOZ_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8A8 ||
+ surface->GetFormat() == SurfaceFormat::B8G8R8X8);
+
+ RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
+ NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
+
+ int32_t width = dataSurface->GetSize().width;
+ int32_t height = dataSurface->GetSize().height;
+ int32_t bytesPerPixel = 4 * sizeof(uint8_t);
+ uint32_t bytesPerRow = bytesPerPixel * width;
+
+ // initialize these bitmap structs which we will later
+ // serialize directly to the head of the bitmap file
+ BITMAPINFOHEADER bmi;
+ bmi.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.biWidth = width;
+ bmi.biHeight = height;
+ bmi.biPlanes = 1;
+ bmi.biBitCount = (WORD)bytesPerPixel*8;
+ bmi.biCompression = BI_RGB;
+ bmi.biSizeImage = bytesPerRow * height;
+ bmi.biXPelsPerMeter = 0;
+ bmi.biYPelsPerMeter = 0;
+ bmi.biClrUsed = 0;
+ bmi.biClrImportant = 0;
+
+ BITMAPFILEHEADER bf;
+ bf.bfType = 0x4D42; // 'BM'
+ bf.bfReserved1 = 0;
+ bf.bfReserved2 = 0;
+ bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
+ bf.bfSize = bf.bfOffBits + bmi.biSizeImage;
+
+ // get a file output stream
+ nsCOMPtr<nsIOutputStream> stream;
+ rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ DataSourceSurface::MappedSurface map;
+ if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // write the bitmap headers and rgb pixel data to the file
+ rv = NS_ERROR_FAILURE;
+ if (stream) {
+ uint32_t written;
+ stream->Write((const char*)&bf, sizeof(BITMAPFILEHEADER), &written);
+ if (written == sizeof(BITMAPFILEHEADER)) {
+ stream->Write((const char*)&bmi, sizeof(BITMAPINFOHEADER), &written);
+ if (written == sizeof(BITMAPINFOHEADER)) {
+ // write out the image data backwards because the desktop won't
+ // show bitmaps with negative heights for top-to-bottom
+ uint32_t i = map.mStride * height;
+ do {
+ i -= map.mStride;
+ stream->Write(((const char*)map.mData) + i, bytesPerRow, &written);
+ if (written == bytesPerRow) {
+ rv = NS_OK;
+ } else {
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+ } while (i != 0);
+ }
+ }
+
+ stream->Close();
+ }
+
+ dataSurface->Unmap();
+
+ return rv;
+}
+
// This is in use here and in dom/events/TouchEvent.cpp
/* static */
uint32_t
WinUtils::IsTouchDeviceSupportPresent()
{
int32_t touchCapabilities = ::GetSystemMetrics(SM_DIGITIZER);
return (touchCapabilities & NID_READY) &&
(touchCapabilities & (NID_EXTERNAL_TOUCH | NID_INTEGRATED_TOUCH));
--- a/widget/windows/WinUtils.h
+++ b/widget/windows/WinUtils.h
@@ -480,16 +480,21 @@ public:
*/
static bool ResolveJunctionPointsAndSymLinks(std::wstring& aPath);
static bool ResolveJunctionPointsAndSymLinks(nsIFile* aPath);
static void Initialize();
static bool ShouldHideScrollbars();
+ static nsresult WriteBitmap(nsIFile* aFile, mozilla::gfx::SourceSurface* surface);
+ // This function is a helper, but it cannot be called from the main thread.
+ // Use the one above!
+ static nsresult WriteBitmap(nsIFile* aFile, imgIContainer* aImage);
+
/**
* This function normalizes the input path, converts short filenames to long
* filenames, and substitutes environment variables for system paths.
* The resulting output string length is guaranteed to be <= MAX_PATH.
*/
static bool SanitizePath(const wchar_t* aInputPath, nsAString& aOutput);
/**
--- a/widget/windows/moz.build
+++ b/widget/windows/moz.build
@@ -83,16 +83,18 @@ UNIFIED_SOURCES += [
]
# The following files cannot be built in unified mode because of name clashes.
SOURCES += [
'JumpListBuilder.cpp',
'nsBidiKeyboard.cpp',
'nsFilePicker.cpp',
'nsWidgetFactory.cpp',
+ 'ToastNotification.cpp',
+ 'ToastNotificationHandler.cpp',
'WinCompositorWidget.cpp',
'WindowsUIUtils.cpp',
'WinMouseScrollHandler.cpp',
]
if CONFIG['NS_PRINTING']:
UNIFIED_SOURCES += [
'nsDeviceContextSpecWin.cpp',
@@ -154,9 +156,11 @@ RESFILE = 'widget.res'
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
OS_LIBS += [
'rpcrt4',
]
if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
# C5038: Suppress initializer list order warnings from wrl.h
+ SOURCES['ToastNotification.cpp'].flags += ['-wd5038']
+ SOURCES['ToastNotificationHandler.cpp'].flags += ['-wd5038']
SOURCES['WindowsUIUtils.cpp'].flags += ['-wd5038']
--- a/widget/windows/nsWidgetFactory.cpp
+++ b/widget/windows/nsWidgetFactory.cpp
@@ -39,16 +39,19 @@
#include "nsBidiKeyboard.h"
#include "nsDragService.h"
#include "nsTransferable.h"
#include "nsHTMLFormatConverter.h"
#include "WinTaskbar.h"
#include "JumpListBuilder.h"
#include "JumpListItem.h"
+// Toast notification support
+#include "ToastNotification.h"
+#include "nsToolkitCompsCID.h"
#include "WindowsUIUtils.h"
#ifdef NS_PRINTING
#include "nsDeviceContextSpecWin.h"
#include "nsPrintDialogWin.h"
#include "nsPrintSettingsServiceWin.h"
#include "nsPrintSession.h"
@@ -132,16 +135,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(JumpListI
NS_GENERIC_FACTORY_CONSTRUCTOR(JumpListSeparator)
NS_GENERIC_FACTORY_CONSTRUCTOR(JumpListLink)
NS_GENERIC_FACTORY_CONSTRUCTOR(JumpListShortcut)
NS_GENERIC_FACTORY_CONSTRUCTOR(WindowsUIUtils)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ToastNotification, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(TaskbarPreviewCallback)
#ifdef NS_PRINTING
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintDialogServiceWin, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSettingsServiceWin, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsPrinterEnumeratorWin)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecWin)
#endif
@@ -171,16 +175,17 @@ NS_DEFINE_NAMED_CID(NS_WIN_TASKBAR_CID);
NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTBUILDER_CID);
NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTITEM_CID);
NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTSEPARATOR_CID);
NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTLINK_CID);
NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTSHORTCUT_CID);
NS_DEFINE_NAMED_CID(NS_WINDOWS_UIUTILS_CID);
NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_BIDIKEYBOARD_CID);
+NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_TASKBARPREVIEWCALLBACK_CID);
#ifdef NS_PRINTING
NS_DEFINE_NAMED_CID(NS_PRINTDIALOGSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_PRINTSETTINGSSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_PRINTER_ENUMERATOR_CID);
NS_DEFINE_NAMED_CID(NS_PRINTSESSION_CID);
NS_DEFINE_NAMED_CID(NS_DEVICE_CONTEXT_SPEC_CID);
#endif
@@ -206,16 +211,17 @@ static const mozilla::Module::CIDEntry k
{ &kNS_WIN_JUMPLISTBUILDER_CID, false, nullptr, JumpListBuilderConstructor },
{ &kNS_WIN_JUMPLISTITEM_CID, false, nullptr, JumpListItemConstructor },
{ &kNS_WIN_JUMPLISTSEPARATOR_CID, false, nullptr, JumpListSeparatorConstructor },
{ &kNS_WIN_JUMPLISTLINK_CID, false, nullptr, JumpListLinkConstructor },
{ &kNS_WIN_JUMPLISTSHORTCUT_CID, false, nullptr, JumpListShortcutConstructor },
{ &kNS_WINDOWS_UIUTILS_CID, false, nullptr, WindowsUIUtilsConstructor },
{ &kNS_DRAGSERVICE_CID, false, nullptr, nsDragServiceConstructor, Module::MAIN_PROCESS_ONLY },
{ &kNS_BIDIKEYBOARD_CID, false, nullptr, nsBidiKeyboardConstructor, Module::MAIN_PROCESS_ONLY },
+ { &kNS_SYSTEMALERTSSERVICE_CID, false, nullptr, ToastNotificationConstructor },
{ &kNS_TASKBARPREVIEWCALLBACK_CID, false, nullptr, TaskbarPreviewCallbackConstructor },
#ifdef NS_PRINTING
{ &kNS_PRINTDIALOGSERVICE_CID, false, nullptr, nsPrintDialogServiceWinConstructor, Module::MAIN_PROCESS_ONLY },
{ &kNS_PRINTSETTINGSSERVICE_CID, false, nullptr, nsPrintSettingsServiceWinConstructor },
{ &kNS_PRINTER_ENUMERATOR_CID, false, nullptr, nsPrinterEnumeratorWinConstructor },
{ &kNS_PRINTSESSION_CID, false, nullptr, nsPrintSessionConstructor },
{ &kNS_DEVICE_CONTEXT_SPEC_CID, false, nullptr, nsDeviceContextSpecWinConstructor },
#endif
@@ -241,16 +247,17 @@ static const mozilla::Module::ContractID
{ "@mozilla.org/windows-jumplistbuilder;1", &kNS_WIN_JUMPLISTBUILDER_CID },
{ "@mozilla.org/windows-jumplistitem;1", &kNS_WIN_JUMPLISTITEM_CID },
{ "@mozilla.org/windows-jumplistseparator;1", &kNS_WIN_JUMPLISTSEPARATOR_CID },
{ "@mozilla.org/windows-jumplistlink;1", &kNS_WIN_JUMPLISTLINK_CID },
{ "@mozilla.org/windows-jumplistshortcut;1", &kNS_WIN_JUMPLISTSHORTCUT_CID },
{ "@mozilla.org/windows-ui-utils;1", &kNS_WINDOWS_UIUTILS_CID },
{ "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID, Module::MAIN_PROCESS_ONLY },
+ { NS_SYSTEMALERTSERVICE_CONTRACTID, &kNS_SYSTEMALERTSSERVICE_CID, Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/widget/taskbar-preview-callback;1", &kNS_TASKBARPREVIEWCALLBACK_CID },
#ifdef NS_PRINTING
{ NS_PRINTDIALOGSERVICE_CONTRACTID, &kNS_PRINTDIALOGSERVICE_CID },
{ "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID },
{ "@mozilla.org/gfx/printerenumerator;1", &kNS_PRINTER_ENUMERATOR_CID },
{ "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID },
{ "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID },
#endif