|
1 /* -*- Mode: C++; tab-width: 2; 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 "mozilla/dom/ContentChild.h" |
|
7 #include "mozilla/dom/PermissionMessageUtils.h" |
|
8 #include "nsXULAppAPI.h" |
|
9 |
|
10 #include "nsAlertsService.h" |
|
11 |
|
12 #ifdef MOZ_WIDGET_ANDROID |
|
13 #include "AndroidBridge.h" |
|
14 using namespace mozilla::widget::android; |
|
15 #else |
|
16 |
|
17 #include "nsXPCOM.h" |
|
18 #include "nsIServiceManager.h" |
|
19 #include "nsIDOMWindow.h" |
|
20 #include "nsPromiseFlatString.h" |
|
21 #include "nsToolkitCompsCID.h" |
|
22 |
|
23 #endif // !MOZ_WIDGET_ANDROID |
|
24 |
|
25 using namespace mozilla; |
|
26 |
|
27 using mozilla::dom::ContentChild; |
|
28 |
|
29 NS_IMPL_ISUPPORTS(nsAlertsService, nsIAlertsService, nsIAlertsProgressListener) |
|
30 |
|
31 nsAlertsService::nsAlertsService() |
|
32 { |
|
33 } |
|
34 |
|
35 nsAlertsService::~nsAlertsService() |
|
36 {} |
|
37 |
|
38 bool nsAlertsService::ShouldShowAlert() |
|
39 { |
|
40 bool result = true; |
|
41 |
|
42 #ifdef XP_WIN |
|
43 HMODULE shellDLL = ::LoadLibraryW(L"shell32.dll"); |
|
44 if (!shellDLL) |
|
45 return result; |
|
46 |
|
47 SHQueryUserNotificationStatePtr pSHQueryUserNotificationState = |
|
48 (SHQueryUserNotificationStatePtr) ::GetProcAddress(shellDLL, "SHQueryUserNotificationState"); |
|
49 |
|
50 if (pSHQueryUserNotificationState) { |
|
51 MOZ_QUERY_USER_NOTIFICATION_STATE qstate; |
|
52 if (SUCCEEDED(pSHQueryUserNotificationState(&qstate))) { |
|
53 if (qstate != QUNS_ACCEPTS_NOTIFICATIONS) { |
|
54 result = false; |
|
55 } |
|
56 } |
|
57 } |
|
58 |
|
59 ::FreeLibrary(shellDLL); |
|
60 #endif |
|
61 |
|
62 return result; |
|
63 } |
|
64 |
|
65 NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl, const nsAString & aAlertTitle, |
|
66 const nsAString & aAlertText, bool aAlertTextClickable, |
|
67 const nsAString & aAlertCookie, |
|
68 nsIObserver * aAlertListener, |
|
69 const nsAString & aAlertName, |
|
70 const nsAString & aBidi, |
|
71 const nsAString & aLang, |
|
72 nsIPrincipal * aPrincipal) |
|
73 { |
|
74 if (XRE_GetProcessType() == GeckoProcessType_Content) { |
|
75 ContentChild* cpc = ContentChild::GetSingleton(); |
|
76 |
|
77 if (aAlertListener) |
|
78 cpc->AddRemoteAlertObserver(PromiseFlatString(aAlertCookie), aAlertListener); |
|
79 |
|
80 cpc->SendShowAlertNotification(PromiseFlatString(aImageUrl), |
|
81 PromiseFlatString(aAlertTitle), |
|
82 PromiseFlatString(aAlertText), |
|
83 aAlertTextClickable, |
|
84 PromiseFlatString(aAlertCookie), |
|
85 PromiseFlatString(aAlertName), |
|
86 PromiseFlatString(aBidi), |
|
87 PromiseFlatString(aLang), |
|
88 IPC::Principal(aPrincipal)); |
|
89 return NS_OK; |
|
90 } |
|
91 |
|
92 #ifdef MOZ_WIDGET_ANDROID |
|
93 mozilla::AndroidBridge::Bridge()->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, |
|
94 aAlertListener, aAlertName); |
|
95 return NS_OK; |
|
96 #else |
|
97 // Check if there is an optional service that handles system-level notifications |
|
98 nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID)); |
|
99 nsresult rv; |
|
100 if (sysAlerts) { |
|
101 return sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, |
|
102 aAlertCookie, aAlertListener, aAlertName, |
|
103 aBidi, aLang, IPC::Principal(aPrincipal)); |
|
104 } |
|
105 |
|
106 if (!ShouldShowAlert()) { |
|
107 // Do not display the alert. Instead call alertfinished and get out. |
|
108 if (aAlertListener) |
|
109 aAlertListener->Observe(nullptr, "alertfinished", PromiseFlatString(aAlertCookie).get()); |
|
110 return NS_OK; |
|
111 } |
|
112 |
|
113 // Use XUL notifications as a fallback if above methods have failed. |
|
114 rv = mXULAlerts.ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, |
|
115 aAlertCookie, aAlertListener, aAlertName, |
|
116 aBidi, aLang); |
|
117 return rv; |
|
118 #endif // !MOZ_WIDGET_ANDROID |
|
119 } |
|
120 |
|
121 NS_IMETHODIMP nsAlertsService::CloseAlert(const nsAString& aAlertName, |
|
122 nsIPrincipal* aPrincipal) |
|
123 { |
|
124 if (XRE_GetProcessType() == GeckoProcessType_Content) { |
|
125 ContentChild* cpc = ContentChild::GetSingleton(); |
|
126 cpc->SendCloseAlert(nsAutoString(aAlertName), IPC::Principal(aPrincipal)); |
|
127 return NS_OK; |
|
128 } |
|
129 |
|
130 #ifdef MOZ_WIDGET_ANDROID |
|
131 mozilla::widget::android::GeckoAppShell::CloseNotification(aAlertName); |
|
132 return NS_OK; |
|
133 #else |
|
134 |
|
135 // Try the system notification service. |
|
136 nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID)); |
|
137 if (sysAlerts) { |
|
138 return sysAlerts->CloseAlert(aAlertName, nullptr); |
|
139 } |
|
140 |
|
141 return mXULAlerts.CloseAlert(aAlertName); |
|
142 #endif // !MOZ_WIDGET_ANDROID |
|
143 } |
|
144 |
|
145 |
|
146 NS_IMETHODIMP nsAlertsService::OnProgress(const nsAString & aAlertName, |
|
147 int64_t aProgress, |
|
148 int64_t aProgressMax, |
|
149 const nsAString & aAlertText) |
|
150 { |
|
151 #ifdef MOZ_WIDGET_ANDROID |
|
152 mozilla::widget::android::GeckoAppShell::AlertsProgressListener_OnProgress(aAlertName, |
|
153 aProgress, aProgressMax, |
|
154 aAlertText); |
|
155 return NS_OK; |
|
156 #else |
|
157 return NS_ERROR_NOT_IMPLEMENTED; |
|
158 #endif // !MOZ_WIDGET_ANDROID |
|
159 } |
|
160 |
|
161 NS_IMETHODIMP nsAlertsService::OnCancel(const nsAString & aAlertName) |
|
162 { |
|
163 #ifdef MOZ_WIDGET_ANDROID |
|
164 mozilla::widget::android::GeckoAppShell::CloseNotification(aAlertName); |
|
165 return NS_OK; |
|
166 #else |
|
167 return NS_ERROR_NOT_IMPLEMENTED; |
|
168 #endif // !MOZ_WIDGET_ANDROID |
|
169 } |