diff -r 000000000000 -r 6474c204b198 toolkit/components/alerts/nsXULAlerts.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolkit/components/alerts/nsXULAlerts.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 2; 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/. */ + +#include "nsXULAlerts.h" + +#include "nsAutoPtr.h" +#include "mozilla/LookAndFeel.h" +#include "nsIServiceManager.h" +#include "nsISupportsArray.h" +#include "nsISupportsPrimitives.h" +#include "nsPIDOMWindow.h" +#include "nsIWindowWatcher.h" + +using namespace mozilla; + +#define ALERT_CHROME_URL "chrome://global/content/alerts/alert.xul" + +NS_IMPL_ISUPPORTS(nsXULAlertObserver, nsIObserver) + +NS_IMETHODIMP +nsXULAlertObserver::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) +{ + if (!strcmp("alertfinished", aTopic)) { + nsIDOMWindow* currentAlert = mXULAlerts->mNamedWindows.GetWeak(mAlertName); + // The window in mNamedWindows might be a replacement, thus it should only + // be removed if it is the same window that is associated with this listener. + if (currentAlert == mAlertWindow) { + mXULAlerts->mNamedWindows.Remove(mAlertName); + } + } + + nsresult rv = NS_OK; + if (mObserver) { + rv = mObserver->Observe(aSubject, aTopic, aData); + } + return rv; +} + +nsresult +nsXULAlerts::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) +{ + nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); + + nsCOMPtr argsArray; + nsresult rv = NS_NewISupportsArray(getter_AddRefs(argsArray)); + NS_ENSURE_SUCCESS(rv, rv); + + // create scriptable versions of our strings that we can store in our nsISupportsArray.... + nsCOMPtr scriptableImageUrl (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); + NS_ENSURE_TRUE(scriptableImageUrl, NS_ERROR_FAILURE); + + scriptableImageUrl->SetData(aImageUrl); + rv = argsArray->AppendElement(scriptableImageUrl); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr scriptableAlertTitle (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); + NS_ENSURE_TRUE(scriptableAlertTitle, NS_ERROR_FAILURE); + + scriptableAlertTitle->SetData(aAlertTitle); + rv = argsArray->AppendElement(scriptableAlertTitle); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr scriptableAlertText (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); + NS_ENSURE_TRUE(scriptableAlertText, NS_ERROR_FAILURE); + + scriptableAlertText->SetData(aAlertText); + rv = argsArray->AppendElement(scriptableAlertText); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr scriptableIsClickable (do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID)); + NS_ENSURE_TRUE(scriptableIsClickable, NS_ERROR_FAILURE); + + scriptableIsClickable->SetData(aAlertTextClickable); + rv = argsArray->AppendElement(scriptableIsClickable); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr scriptableAlertCookie (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); + NS_ENSURE_TRUE(scriptableAlertCookie, NS_ERROR_FAILURE); + + scriptableAlertCookie->SetData(aAlertCookie); + rv = argsArray->AppendElement(scriptableAlertCookie); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr scriptableOrigin (do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID)); + NS_ENSURE_TRUE(scriptableOrigin, NS_ERROR_FAILURE); + + int32_t origin = + LookAndFeel::GetInt(LookAndFeel::eIntID_AlertNotificationOrigin); + scriptableOrigin->SetData(origin); + + rv = argsArray->AppendElement(scriptableOrigin); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr scriptableBidi (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); + NS_ENSURE_TRUE(scriptableBidi, NS_ERROR_FAILURE); + + scriptableBidi->SetData(aBidi); + rv = argsArray->AppendElement(scriptableBidi); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr scriptableLang (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); + NS_ENSURE_TRUE(scriptableLang, NS_ERROR_FAILURE); + + scriptableLang->SetData(aLang); + rv = argsArray->AppendElement(scriptableLang); + NS_ENSURE_SUCCESS(rv, rv); + + // Alerts with the same name should replace the old alert in the same position. + // Provide the new alert window with a pointer to the replaced window so that + // it may take the same position. + nsCOMPtr replacedWindow = do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv); + NS_ENSURE_TRUE(replacedWindow, NS_ERROR_FAILURE); + nsIDOMWindow* previousAlert = mNamedWindows.GetWeak(aAlertName); + replacedWindow->SetData(previousAlert); + replacedWindow->SetDataIID(&NS_GET_IID(nsIDOMWindow)); + rv = argsArray->AppendElement(replacedWindow); + NS_ENSURE_SUCCESS(rv, rv); + + // Add an observer (that wraps aAlertListener) to remove the window from + // mNamedWindows when it is closed. + nsCOMPtr ifptr = do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + nsRefPtr alertObserver = new nsXULAlertObserver(this, aAlertName, aAlertListener); + nsCOMPtr iSupports(do_QueryInterface(alertObserver)); + ifptr->SetData(iSupports); + ifptr->SetDataIID(&NS_GET_IID(nsIObserver)); + rv = argsArray->AppendElement(ifptr); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr newWindow; + rv = wwatch->OpenWindow(0, ALERT_CHROME_URL, "_blank", + "chrome,dialog=yes,titlebar=no,popup=yes", argsArray, + getter_AddRefs(newWindow)); + NS_ENSURE_SUCCESS(rv, rv); + + mNamedWindows.Put(aAlertName, newWindow); + alertObserver->SetAlertWindow(newWindow); + + return NS_OK; +} + +nsresult +nsXULAlerts::CloseAlert(const nsAString& aAlertName) +{ + nsIDOMWindow* alert = mNamedWindows.GetWeak(aAlertName); + nsCOMPtr domWindow = do_QueryInterface(alert); + if (domWindow) { + domWindow->DispatchCustomEvent("XULAlertClose"); + } + return NS_OK; +} +