michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsXULAlerts.h" michael@0: michael@0: #include "nsAutoPtr.h" michael@0: #include "mozilla/LookAndFeel.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "nsISupportsArray.h" michael@0: #include "nsISupportsPrimitives.h" michael@0: #include "nsPIDOMWindow.h" michael@0: #include "nsIWindowWatcher.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: #define ALERT_CHROME_URL "chrome://global/content/alerts/alert.xul" michael@0: michael@0: NS_IMPL_ISUPPORTS(nsXULAlertObserver, nsIObserver) michael@0: michael@0: NS_IMETHODIMP michael@0: nsXULAlertObserver::Observe(nsISupports* aSubject, const char* aTopic, michael@0: const char16_t* aData) michael@0: { michael@0: if (!strcmp("alertfinished", aTopic)) { michael@0: nsIDOMWindow* currentAlert = mXULAlerts->mNamedWindows.GetWeak(mAlertName); michael@0: // The window in mNamedWindows might be a replacement, thus it should only michael@0: // be removed if it is the same window that is associated with this listener. michael@0: if (currentAlert == mAlertWindow) { michael@0: mXULAlerts->mNamedWindows.Remove(mAlertName); michael@0: } michael@0: } michael@0: michael@0: nsresult rv = NS_OK; michael@0: if (mObserver) { michael@0: rv = mObserver->Observe(aSubject, aTopic, aData); michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: nsresult michael@0: nsXULAlerts::ShowAlertNotification(const nsAString& aImageUrl, const nsAString& aAlertTitle, michael@0: const nsAString& aAlertText, bool aAlertTextClickable, michael@0: const nsAString& aAlertCookie, nsIObserver* aAlertListener, michael@0: const nsAString& aAlertName, const nsAString& aBidi, michael@0: const nsAString& aLang) michael@0: { michael@0: nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); michael@0: michael@0: nsCOMPtr argsArray; michael@0: nsresult rv = NS_NewISupportsArray(getter_AddRefs(argsArray)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // create scriptable versions of our strings that we can store in our nsISupportsArray.... michael@0: nsCOMPtr scriptableImageUrl (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); michael@0: NS_ENSURE_TRUE(scriptableImageUrl, NS_ERROR_FAILURE); michael@0: michael@0: scriptableImageUrl->SetData(aImageUrl); michael@0: rv = argsArray->AppendElement(scriptableImageUrl); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr scriptableAlertTitle (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); michael@0: NS_ENSURE_TRUE(scriptableAlertTitle, NS_ERROR_FAILURE); michael@0: michael@0: scriptableAlertTitle->SetData(aAlertTitle); michael@0: rv = argsArray->AppendElement(scriptableAlertTitle); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr scriptableAlertText (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); michael@0: NS_ENSURE_TRUE(scriptableAlertText, NS_ERROR_FAILURE); michael@0: michael@0: scriptableAlertText->SetData(aAlertText); michael@0: rv = argsArray->AppendElement(scriptableAlertText); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr scriptableIsClickable (do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID)); michael@0: NS_ENSURE_TRUE(scriptableIsClickable, NS_ERROR_FAILURE); michael@0: michael@0: scriptableIsClickable->SetData(aAlertTextClickable); michael@0: rv = argsArray->AppendElement(scriptableIsClickable); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr scriptableAlertCookie (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); michael@0: NS_ENSURE_TRUE(scriptableAlertCookie, NS_ERROR_FAILURE); michael@0: michael@0: scriptableAlertCookie->SetData(aAlertCookie); michael@0: rv = argsArray->AppendElement(scriptableAlertCookie); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr scriptableOrigin (do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID)); michael@0: NS_ENSURE_TRUE(scriptableOrigin, NS_ERROR_FAILURE); michael@0: michael@0: int32_t origin = michael@0: LookAndFeel::GetInt(LookAndFeel::eIntID_AlertNotificationOrigin); michael@0: scriptableOrigin->SetData(origin); michael@0: michael@0: rv = argsArray->AppendElement(scriptableOrigin); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr scriptableBidi (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); michael@0: NS_ENSURE_TRUE(scriptableBidi, NS_ERROR_FAILURE); michael@0: michael@0: scriptableBidi->SetData(aBidi); michael@0: rv = argsArray->AppendElement(scriptableBidi); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr scriptableLang (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); michael@0: NS_ENSURE_TRUE(scriptableLang, NS_ERROR_FAILURE); michael@0: michael@0: scriptableLang->SetData(aLang); michael@0: rv = argsArray->AppendElement(scriptableLang); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // Alerts with the same name should replace the old alert in the same position. michael@0: // Provide the new alert window with a pointer to the replaced window so that michael@0: // it may take the same position. michael@0: nsCOMPtr replacedWindow = do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv); michael@0: NS_ENSURE_TRUE(replacedWindow, NS_ERROR_FAILURE); michael@0: nsIDOMWindow* previousAlert = mNamedWindows.GetWeak(aAlertName); michael@0: replacedWindow->SetData(previousAlert); michael@0: replacedWindow->SetDataIID(&NS_GET_IID(nsIDOMWindow)); michael@0: rv = argsArray->AppendElement(replacedWindow); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // Add an observer (that wraps aAlertListener) to remove the window from michael@0: // mNamedWindows when it is closed. michael@0: nsCOMPtr ifptr = do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: nsRefPtr alertObserver = new nsXULAlertObserver(this, aAlertName, aAlertListener); michael@0: nsCOMPtr iSupports(do_QueryInterface(alertObserver)); michael@0: ifptr->SetData(iSupports); michael@0: ifptr->SetDataIID(&NS_GET_IID(nsIObserver)); michael@0: rv = argsArray->AppendElement(ifptr); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr newWindow; michael@0: rv = wwatch->OpenWindow(0, ALERT_CHROME_URL, "_blank", michael@0: "chrome,dialog=yes,titlebar=no,popup=yes", argsArray, michael@0: getter_AddRefs(newWindow)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: mNamedWindows.Put(aAlertName, newWindow); michael@0: alertObserver->SetAlertWindow(newWindow); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsXULAlerts::CloseAlert(const nsAString& aAlertName) michael@0: { michael@0: nsIDOMWindow* alert = mNamedWindows.GetWeak(aAlertName); michael@0: nsCOMPtr domWindow = do_QueryInterface(alert); michael@0: if (domWindow) { michael@0: domWindow->DispatchCustomEvent("XULAlertClose"); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: