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 "nsIPrincipal.h"
10 #include "nsIURI.h"
11
12 namespace mozilla {
13 namespace widget {
14
15 NS_IMPL_ISUPPORTS(AndroidAlerts, nsIAlertsService)
16
17 StaticAutoPtr<AndroidAlerts::ListenerMap> AndroidAlerts::sListenerMap;
18 nsTHashMap<nsStringHashKey, java::WebNotification::GlobalRef>
19 AndroidAlerts::mNotificationsMap;
20
21 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)22 AndroidAlerts::ShowAlertNotification(
23 const nsAString& aImageUrl, const nsAString& aAlertTitle,
24 const nsAString& aAlertText, bool aAlertTextClickable,
25 const nsAString& aAlertCookie, nsIObserver* aAlertListener,
26 const nsAString& aAlertName, const nsAString& aBidi, const nsAString& aLang,
27 const nsAString& aData, nsIPrincipal* aPrincipal, bool aInPrivateBrowsing,
28 bool aRequireInteraction) {
29 MOZ_ASSERT_UNREACHABLE("Should be implemented by nsAlertsService.");
30 return NS_ERROR_NOT_IMPLEMENTED;
31 }
32
33 NS_IMETHODIMP
ShowAlert(nsIAlertNotification * aAlert,nsIObserver * aAlertListener)34 AndroidAlerts::ShowAlert(nsIAlertNotification* aAlert,
35 nsIObserver* aAlertListener) {
36 return ShowPersistentNotification(u""_ns, aAlert, aAlertListener);
37 }
38
39 NS_IMETHODIMP
ShowPersistentNotification(const nsAString & aPersistentData,nsIAlertNotification * aAlert,nsIObserver * aAlertListener)40 AndroidAlerts::ShowPersistentNotification(const nsAString& aPersistentData,
41 nsIAlertNotification* aAlert,
42 nsIObserver* aAlertListener) {
43 // nsAlertsService disables our alerts backend if we ever return failure
44 // here. To keep the backend enabled, we always return NS_OK even if we
45 // encounter an error here.
46 nsresult rv;
47
48 nsAutoString imageUrl;
49 rv = aAlert->GetImageURL(imageUrl);
50 NS_ENSURE_SUCCESS(rv, NS_OK);
51
52 nsAutoString title;
53 rv = aAlert->GetTitle(title);
54 NS_ENSURE_SUCCESS(rv, NS_OK);
55
56 nsAutoString text;
57 rv = aAlert->GetText(text);
58 NS_ENSURE_SUCCESS(rv, NS_OK);
59
60 nsAutoString cookie;
61 rv = aAlert->GetCookie(cookie);
62 NS_ENSURE_SUCCESS(rv, NS_OK);
63
64 nsAutoString name;
65 rv = aAlert->GetName(name);
66 NS_ENSURE_SUCCESS(rv, NS_OK);
67
68 nsAutoString lang;
69 rv = aAlert->GetLang(lang);
70 NS_ENSURE_SUCCESS(rv, NS_OK);
71
72 nsAutoString dir;
73 rv = aAlert->GetDir(dir);
74 NS_ENSURE_SUCCESS(rv, NS_OK);
75
76 bool requireInteraction;
77 rv = aAlert->GetRequireInteraction(&requireInteraction);
78 NS_ENSURE_SUCCESS(rv, NS_OK);
79
80 nsCOMPtr<nsIURI> uri;
81 rv = aAlert->GetURI(getter_AddRefs(uri));
82 NS_ENSURE_SUCCESS(rv, NS_OK);
83
84 nsCString spec;
85 if (uri) {
86 rv = uri->GetDisplaySpec(spec);
87 NS_ENSURE_SUCCESS(rv, NS_OK);
88 }
89
90 bool silent;
91 rv = aAlert->GetSilent(&silent);
92 NS_ENSURE_SUCCESS(rv, NS_OK);
93
94 nsTArray<uint32_t> vibrate;
95 rv = aAlert->GetVibrate(vibrate);
96 NS_ENSURE_SUCCESS(rv, NS_OK);
97
98 if (aPersistentData.IsEmpty() && aAlertListener) {
99 if (!sListenerMap) {
100 sListenerMap = new ListenerMap();
101 }
102 // This will remove any observers already registered for this name.
103 sListenerMap->InsertOrUpdate(name, aAlertListener);
104 }
105
106 java::WebNotification::LocalRef notification = notification->New(
107 title, name, cookie, text, imageUrl, dir, lang, requireInteraction, spec,
108 silent, jni::IntArray::From(vibrate));
109 java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
110 if (runtime != NULL) {
111 runtime->NotifyOnShow(notification);
112 }
113 mNotificationsMap.InsertOrUpdate(name, notification);
114
115 return NS_OK;
116 }
117
118 NS_IMETHODIMP
CloseAlert(const nsAString & aAlertName)119 AndroidAlerts::CloseAlert(const nsAString& aAlertName) {
120 java::WebNotification::LocalRef notification =
121 mNotificationsMap.Get(aAlertName);
122 if (!notification) {
123 return NS_OK;
124 }
125
126 java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
127 if (runtime != NULL) {
128 runtime->NotifyOnClose(notification);
129 }
130 mNotificationsMap.Remove(aAlertName);
131
132 return NS_OK;
133 }
134
NotifyListener(const nsAString & aName,const char * aTopic,const char16_t * aCookie)135 void AndroidAlerts::NotifyListener(const nsAString& aName, const char* aTopic,
136 const char16_t* aCookie) {
137 if (!sListenerMap) {
138 return;
139 }
140
141 nsCOMPtr<nsIObserver> listener = sListenerMap->Get(aName);
142 if (!listener) {
143 return;
144 }
145
146 listener->Observe(nullptr, aTopic, aCookie);
147
148 if ("alertfinished"_ns.Equals(aTopic)) {
149 sListenerMap->Remove(aName);
150 mNotificationsMap.Remove(aName);
151 }
152 }
153
154 } // namespace widget
155 } // namespace mozilla
156