summaryrefslogtreecommitdiffstats
path: root/widget/android/AndroidAlerts.cpp
blob: 456dc08290be963ae72dc15240da4e47b8221e78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* -*- Mode: c++; tab-width: 4; 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 "AndroidAlerts.h"
#include "mozilla/java/GeckoRuntimeWrappers.h"
#include "mozilla/java/WebNotificationWrappers.h"
#include "nsIPrincipal.h"
#include "nsIURI.h"

namespace mozilla {
namespace widget {

NS_IMPL_ISUPPORTS(AndroidAlerts, nsIAlertsService)

StaticAutoPtr<AndroidAlerts::ListenerMap> AndroidAlerts::sListenerMap;
nsTHashMap<nsStringHashKey, java::WebNotification::GlobalRef>
    AndroidAlerts::mNotificationsMap;

NS_IMETHODIMP
AndroidAlerts::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) {
  MOZ_ASSERT_UNREACHABLE("Should be implemented by nsAlertsService.");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
AndroidAlerts::ShowAlert(nsIAlertNotification* aAlert,
                         nsIObserver* aAlertListener) {
  return ShowPersistentNotification(u""_ns, aAlert, aAlertListener);
}

NS_IMETHODIMP
AndroidAlerts::ShowPersistentNotification(const nsAString& aPersistentData,
                                          nsIAlertNotification* aAlert,
                                          nsIObserver* aAlertListener) {
  // nsAlertsService disables our alerts backend if we ever return failure
  // here. To keep the backend enabled, we always return NS_OK even if we
  // encounter an error here.
  nsresult rv;

  nsAutoString imageUrl;
  rv = aAlert->GetImageURL(imageUrl);
  NS_ENSURE_SUCCESS(rv, NS_OK);

  nsAutoString title;
  rv = aAlert->GetTitle(title);
  NS_ENSURE_SUCCESS(rv, NS_OK);

  nsAutoString text;
  rv = aAlert->GetText(text);
  NS_ENSURE_SUCCESS(rv, NS_OK);

  nsAutoString cookie;
  rv = aAlert->GetCookie(cookie);
  NS_ENSURE_SUCCESS(rv, NS_OK);

  nsAutoString name;
  rv = aAlert->GetName(name);
  NS_ENSURE_SUCCESS(rv, NS_OK);

  nsAutoString lang;
  rv = aAlert->GetLang(lang);
  NS_ENSURE_SUCCESS(rv, NS_OK);

  nsAutoString dir;
  rv = aAlert->GetDir(dir);
  NS_ENSURE_SUCCESS(rv, NS_OK);

  bool requireInteraction;
  rv = aAlert->GetRequireInteraction(&requireInteraction);
  NS_ENSURE_SUCCESS(rv, NS_OK);

  nsCOMPtr<nsIURI> uri;
  rv = aAlert->GetURI(getter_AddRefs(uri));
  NS_ENSURE_SUCCESS(rv, NS_OK);

  nsCString spec;
  if (uri) {
    rv = uri->GetDisplaySpec(spec);
    NS_ENSURE_SUCCESS(rv, NS_OK);
  }

  bool silent;
  rv = aAlert->GetSilent(&silent);
  NS_ENSURE_SUCCESS(rv, NS_OK);

  bool privateBrowsing;
  rv = aAlert->GetInPrivateBrowsing(&privateBrowsing);
  NS_ENSURE_SUCCESS(rv, NS_OK);

  nsTArray<uint32_t> vibrate;
  rv = aAlert->GetVibrate(vibrate);
  NS_ENSURE_SUCCESS(rv, NS_OK);

  if (aPersistentData.IsEmpty() && aAlertListener) {
    if (!sListenerMap) {
      sListenerMap = new ListenerMap();
    }
    // This will remove any observers already registered for this name.
    sListenerMap->InsertOrUpdate(name, aAlertListener);
  }

  java::WebNotification::LocalRef notification = notification->New(
      title, name, cookie, text, imageUrl, dir, lang, requireInteraction, spec,
      silent, privateBrowsing, jni::IntArray::From(vibrate));
  java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
  if (runtime != NULL) {
    runtime->NotifyOnShow(notification);
  }
  mNotificationsMap.InsertOrUpdate(name, notification);

  return NS_OK;
}

NS_IMETHODIMP
AndroidAlerts::CloseAlert(const nsAString& aAlertName, bool aContextClosed) {
  java::WebNotification::LocalRef notification =
      mNotificationsMap.Get(aAlertName);
  if (!notification) {
    return NS_OK;
  }

  java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
  if (runtime != NULL) {
    runtime->NotifyOnClose(notification);
  }
  mNotificationsMap.Remove(aAlertName);

  return NS_OK;
}

void AndroidAlerts::NotifyListener(const nsAString& aName, const char* aTopic,
                                   const char16_t* aCookie) {
  if (!sListenerMap) {
    return;
  }

  nsCOMPtr<nsIObserver> listener = sListenerMap->Get(aName);
  if (!listener) {
    return;
  }

  listener->Observe(nullptr, aTopic, aCookie);

  if ("alertfinished"_ns.Equals(aTopic)) {
    sListenerMap->Remove(aName);
    mNotificationsMap.Remove(aName);
  }
}

}  // namespace widget
}  // namespace mozilla