1 /* -*- Mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "AndroidAlerts.h"
7 #include "mozilla/java/GeckoRuntimeWrappers.h"
8 #include "mozilla/java/WebNotificationWrappers.h"
9 #include "nsAlertsUtils.h"
10
11 namespace mozilla {
12 namespace widget {
13
14 NS_IMPL_ISUPPORTS(AndroidAlerts, nsIAlertsService)
15
16 StaticAutoPtr<AndroidAlerts::ListenerMap> AndroidAlerts::sListenerMap;
17 nsDataHashtable<nsStringHashKey, java::WebNotification::GlobalRef>
18 AndroidAlerts::mNotificationsMap;
19
20 NS_IMETHODIMP
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)21 AndroidAlerts::ShowAlertNotification(
22 const nsAString& aImageUrl, const nsAString& aAlertTitle,
23 const nsAString& aAlertText, bool aAlertTextClickable,
24 const nsAString& aAlertCookie, nsIObserver* aAlertListener,
25 const nsAString& aAlertName, const nsAString& aBidi, const nsAString& aLang,
26 const nsAString& aData, nsIPrincipal* aPrincipal, bool aInPrivateBrowsing,
27 bool aRequireInteraction) {
28 MOZ_ASSERT_UNREACHABLE("Should be implemented by nsAlertsService.");
29 return NS_ERROR_NOT_IMPLEMENTED;
30 }
31
32 NS_IMETHODIMP
ShowAlert(nsIAlertNotification * aAlert,nsIObserver * aAlertListener)33 AndroidAlerts::ShowAlert(nsIAlertNotification* aAlert,
34 nsIObserver* aAlertListener) {
35 return ShowPersistentNotification(EmptyString(), aAlert, aAlertListener);
36 }
37
38 NS_IMETHODIMP
ShowPersistentNotification(const nsAString & aPersistentData,nsIAlertNotification * aAlert,nsIObserver * aAlertListener)39 AndroidAlerts::ShowPersistentNotification(const nsAString& aPersistentData,
40 nsIAlertNotification* aAlert,
41 nsIObserver* aAlertListener) {
42 // nsAlertsService disables our alerts backend if we ever return failure
43 // here. To keep the backend enabled, we always return NS_OK even if we
44 // encounter an error here.
45 nsresult rv;
46
47 nsAutoString imageUrl;
48 rv = aAlert->GetImageURL(imageUrl);
49 NS_ENSURE_SUCCESS(rv, NS_OK);
50
51 nsAutoString title;
52 rv = aAlert->GetTitle(title);
53 NS_ENSURE_SUCCESS(rv, NS_OK);
54
55 nsAutoString text;
56 rv = aAlert->GetText(text);
57 NS_ENSURE_SUCCESS(rv, NS_OK);
58
59 nsAutoString cookie;
60 rv = aAlert->GetCookie(cookie);
61 NS_ENSURE_SUCCESS(rv, NS_OK);
62
63 nsAutoString name;
64 rv = aAlert->GetName(name);
65 NS_ENSURE_SUCCESS(rv, NS_OK);
66
67 nsAutoString lang;
68 rv = aAlert->GetLang(lang);
69 NS_ENSURE_SUCCESS(rv, NS_OK);
70
71 nsAutoString dir;
72 rv = aAlert->GetDir(dir);
73 NS_ENSURE_SUCCESS(rv, NS_OK);
74
75 bool requireInteraction;
76 rv = aAlert->GetRequireInteraction(&requireInteraction);
77 NS_ENSURE_SUCCESS(rv, NS_OK);
78
79 nsCOMPtr<nsIPrincipal> principal;
80 rv = aAlert->GetPrincipal(getter_AddRefs(principal));
81 NS_ENSURE_SUCCESS(rv, NS_OK);
82
83 nsAutoString host;
84 nsAlertsUtils::GetSourceHostPort(principal, host);
85
86 if (aPersistentData.IsEmpty() && aAlertListener) {
87 if (!sListenerMap) {
88 sListenerMap = new ListenerMap();
89 }
90 // This will remove any observers already registered for this name.
91 sListenerMap->Put(name, aAlertListener);
92 }
93
94 java::WebNotification::LocalRef notification = notification->New(
95 title, name, cookie, text, imageUrl, dir, lang, requireInteraction);
96 java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
97 if (runtime != NULL) {
98 runtime->NotifyOnShow(notification);
99 }
100 mNotificationsMap.Put(name, notification);
101
102 return NS_OK;
103 }
104
105 NS_IMETHODIMP
CloseAlert(const nsAString & aAlertName,nsIPrincipal * aPrincipal)106 AndroidAlerts::CloseAlert(const nsAString& aAlertName,
107 nsIPrincipal* aPrincipal) {
108 java::WebNotification::LocalRef notification =
109 mNotificationsMap.Get(aAlertName);
110 if (!notification) {
111 return NS_OK;
112 }
113
114 java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
115 if (runtime != NULL) {
116 runtime->NotifyOnClose(notification);
117 }
118 mNotificationsMap.Remove(aAlertName);
119
120 return NS_OK;
121 }
122
NotifyListener(const nsAString & aName,const char * aTopic,const char16_t * aCookie)123 void AndroidAlerts::NotifyListener(const nsAString& aName, const char* aTopic,
124 const char16_t* aCookie) {
125 if (!sListenerMap) {
126 return;
127 }
128
129 nsCOMPtr<nsIObserver> listener = sListenerMap->Get(aName);
130 if (!listener) {
131 return;
132 }
133
134 listener->Observe(nullptr, aTopic, aCookie);
135
136 if (NS_LITERAL_CSTRING("alertfinished").Equals(aTopic)) {
137 sListenerMap->Remove(aName);
138 mNotificationsMap.Remove(aName);
139 }
140 }
141
142 } // namespace widget
143 } // namespace mozilla
144