summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebNotification.java
blob: c2de231f8042072bd07be0f6a1c4cc38e56d27c4 (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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/* 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/. */

package org.mozilla.geckoview;

import android.os.Parcel;
import android.os.ParcelFormatException;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.util.ThreadUtils;

/**
 * This class represents a single <a
 * href="https://developer.mozilla.org/en-US/docs/Web/API/Notification">Web Notification</a>. These
 * can be received by connecting a {@link WebNotificationDelegate} to {@link GeckoRuntime} via
 * {@link GeckoRuntime#setWebNotificationDelegate(WebNotificationDelegate)}.
 */
public class WebNotification implements Parcelable {

  /**
   * Title is shown at the top of the notification window.
   *
   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Notification/title">Web
   *     Notification - title</a>
   */
  public final @Nullable String title;

  /**
   * Tag is the ID of the notification.
   *
   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Notification/tag">Web
   *     Notification - tag</a>
   */
  public final @NonNull String tag;

  private final @Nullable String mCookie;

  /**
   * Text represents the body of the notification.
   *
   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Notification/body">Web
   *     Notification - text</a>
   */
  public final @Nullable String text;

  /**
   * ImageURL contains the URL of an icon to be displayed as part of the notification.
   *
   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Notification/icon">Web
   *     Notification - icon</a>
   */
  public final @Nullable String imageUrl;

  /**
   * TextDirection indicates the direction that the language of the text is displayed. Possible
   * values are: auto: adopts the browser's language setting behaviour (the default.) ltr: left to
   * right. rtl: right to left.
   *
   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Notification/dir">Web
   *     Notification - dir</a>
   */
  public final @Nullable String textDirection;

  /**
   * Lang indicates the notification's language, as specified using a DOMString representing a BCP
   * 47 language tag.
   *
   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMString">DOM String</a>
   * @see <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">BCP 47</a>
   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Notification/lang">Web
   *     Notification - lang</a>
   */
  public final @Nullable String lang;

  /**
   * RequireInteraction indicates whether a notification should remain active until the user clicks
   * or dismisses it, rather than closing automatically.
   *
   * @see <a
   *     href="https://developer.mozilla.org/en-US/docs/Web/API/Notification/requireInteraction">Web
   *     Notification - requireInteraction</a>
   */
  public final @NonNull boolean requireInteraction;

  /**
   * This is the URL of the page or Service Worker that generated the notification. Null if this
   * notification was not generated by a Web Page (e.g. from an Extension).
   *
   * <p>TODO: make NonNull once we have Bug 1589693
   */
  public final @Nullable String source;

  /**
   * When set, indicates that no sounds or vibrations should be made.
   *
   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Notification/silent">Web
   *     Notification - silent</a>
   */
  public final boolean silent;

  /** indicates whether the notification came from private browsing mode or not. */
  public final boolean privateBrowsing;

  /**
   * A vibration pattern to run with the display of the notification. A vibration pattern can be an
   * array with as few as one member. The values are times in milliseconds where the even indices
   * (0, 2, 4, etc.) indicate how long to vibrate and the odd indices indicate how long to pause.
   * For example, [300, 100, 400] would vibrate 300ms, pause 100ms, then vibrate 400ms.
   *
   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Notification/vibrate">Web
   *     Notification - vibrate</a>
   */
  public final @NonNull int[] vibrate;

  @WrapForJNI
  /* package */ WebNotification(
      @Nullable final String title,
      @NonNull final String tag,
      @Nullable final String cookie,
      @Nullable final String text,
      @Nullable final String imageUrl,
      @Nullable final String textDirection,
      @Nullable final String lang,
      @NonNull final boolean requireInteraction,
      @NonNull final String source,
      final boolean silent,
      final boolean privateBrowsing,
      @NonNull final int[] vibrate) {
    this.tag = tag;
    this.mCookie = cookie;
    this.title = title;
    this.text = text;
    this.imageUrl = imageUrl;
    this.textDirection = textDirection;
    this.lang = lang;
    this.requireInteraction = requireInteraction;
    this.source = "".equals(source) ? null : source;
    this.silent = silent;
    this.vibrate = vibrate;
    this.privateBrowsing = privateBrowsing;
  }

  /**
   * This should be called when the user taps or clicks a notification. Note that this does not
   * automatically dismiss the notification as far as Web Content is concerned. For that, see {@link
   * #dismiss()}.
   */
  @UiThread
  public void click() {
    ThreadUtils.assertOnUiThread();
    GeckoAppShell.onNotificationClick(tag, mCookie);
  }

  /**
   * This should be called when the app stops showing the notification. This is important, as there
   * may be a limit to the number of active notifications each site can display.
   */
  @UiThread
  public void dismiss() {
    ThreadUtils.assertOnUiThread();
    GeckoAppShell.onNotificationClose(tag, mCookie);
  }

  // Increment this value whenever anything changes in the parcelable representation.
  private static final int VERSION = 1;

  // To avoid TransactionTooLargeException, we only store small imageUrls
  private static final int IMAGE_URL_LENGTH_MAX = 150;

  @Override
  public int describeContents() {
    return 0;
  }

  @Override
  public void writeToParcel(final Parcel dest, final int flags) {
    dest.writeInt(VERSION);
    dest.writeString(title);
    dest.writeString(tag);
    dest.writeString(mCookie);
    dest.writeString(text);
    if (imageUrl.length() < IMAGE_URL_LENGTH_MAX) {
      dest.writeString(imageUrl);
    } else {
      dest.writeString("");
    }
    dest.writeString(textDirection);
    dest.writeString(lang);
    dest.writeInt(requireInteraction ? 1 : 0);
    dest.writeString(source);
    dest.writeInt(silent ? 1 : 0);
    dest.writeInt(privateBrowsing ? 1 : 0);
    dest.writeIntArray(vibrate);
  }

  private WebNotification(final Parcel in) {
    title = in.readString();
    tag = in.readString();
    mCookie = in.readString();
    text = in.readString();
    imageUrl = in.readString();
    textDirection = in.readString();
    lang = in.readString();
    requireInteraction = in.readInt() == 1;
    source = in.readString();
    silent = in.readInt() == 1;
    privateBrowsing = in.readInt() == 1;
    vibrate = in.createIntArray();
  }

  public static final Creator<WebNotification> CREATOR =
      new Creator<>() {
        @Override
        public WebNotification createFromParcel(final Parcel in) {
          final int version = in.readInt();
          if (version != VERSION) {
            throw new ParcelFormatException(
                "Mismatched version: " + version + " expected: " + VERSION);
          }
          return new WebNotification(in);
        }

        @Override
        public WebNotification[] newArray(final int size) {
          return new WebNotification[size];
        }
      };
}