1 | import '@firebase/installations';
|
2 | import { Component } from '@firebase/component';
|
3 | import { openDb, deleteDb } from 'idb';
|
4 | import { ErrorFactory, isIndexedDBAvailable, validateIndexedDBOpenable, getModularInstance } from '@firebase/util';
|
5 | import { _registerComponent, getApp, _getProvider } from '@firebase/app';
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | const DEFAULT_VAPID_KEY = 'BDOU99-h67HcA6JeFXHbSNMu7e2yNNu3RzoMj8TM4W88jITfq7ZmPvIM1Iv-4_l2LxQcYwhqby2xGpWwzjfAnG4';
|
24 | const ENDPOINT = 'https://fcmregistrations.googleapis.com/v1';
|
25 |
|
26 | const FCM_MSG = 'FCM_MSG';
|
27 | const CONSOLE_CAMPAIGN_ID = 'google.c.a.c_id';
|
28 |
|
29 | const SDK_PLATFORM_WEB = 3;
|
30 | const EVENT_MESSAGE_DELIVERED = 1;
|
31 | var MessageType$1;
|
32 | (function (MessageType) {
|
33 | MessageType[MessageType["DATA_MESSAGE"] = 1] = "DATA_MESSAGE";
|
34 | MessageType[MessageType["DISPLAY_NOTIFICATION"] = 3] = "DISPLAY_NOTIFICATION";
|
35 | })(MessageType$1 || (MessageType$1 = {}));
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 | var MessageType;
|
52 | (function (MessageType) {
|
53 | MessageType["PUSH_RECEIVED"] = "push-received";
|
54 | MessageType["NOTIFICATION_CLICKED"] = "notification-clicked";
|
55 | })(MessageType || (MessageType = {}));
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 | function arrayToBase64(array) {
|
74 | const uint8Array = new Uint8Array(array);
|
75 | const base64String = btoa(String.fromCharCode(...uint8Array));
|
76 | return base64String.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
77 | }
|
78 | function base64ToArray(base64String) {
|
79 | const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
|
80 | const base64 = (base64String + padding)
|
81 | .replace(/\-/g, '+')
|
82 | .replace(/_/g, '/');
|
83 | const rawData = atob(base64);
|
84 | const outputArray = new Uint8Array(rawData.length);
|
85 | for (let i = 0; i < rawData.length; ++i) {
|
86 | outputArray[i] = rawData.charCodeAt(i);
|
87 | }
|
88 | return outputArray;
|
89 | }
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | const OLD_DB_NAME = 'fcm_token_details_db';
|
108 |
|
109 |
|
110 |
|
111 |
|
112 | const OLD_DB_VERSION = 5;
|
113 | const OLD_OBJECT_STORE_NAME = 'fcm_token_object_Store';
|
114 | async function migrateOldDatabase(senderId) {
|
115 | if ('databases' in indexedDB) {
|
116 |
|
117 |
|
118 | const databases = await indexedDB.databases();
|
119 | const dbNames = databases.map(db => db.name);
|
120 | if (!dbNames.includes(OLD_DB_NAME)) {
|
121 |
|
122 | return null;
|
123 | }
|
124 | }
|
125 | let tokenDetails = null;
|
126 | const db = await openDb(OLD_DB_NAME, OLD_DB_VERSION, async (db) => {
|
127 | var _a;
|
128 | if (db.oldVersion < 2) {
|
129 |
|
130 | return;
|
131 | }
|
132 | if (!db.objectStoreNames.contains(OLD_OBJECT_STORE_NAME)) {
|
133 |
|
134 | return;
|
135 | }
|
136 | const objectStore = db.transaction.objectStore(OLD_OBJECT_STORE_NAME);
|
137 | const value = await objectStore.index('fcmSenderId').get(senderId);
|
138 | await objectStore.clear();
|
139 | if (!value) {
|
140 |
|
141 | return;
|
142 | }
|
143 | if (db.oldVersion === 2) {
|
144 | const oldDetails = value;
|
145 | if (!oldDetails.auth || !oldDetails.p256dh || !oldDetails.endpoint) {
|
146 | return;
|
147 | }
|
148 | tokenDetails = {
|
149 | token: oldDetails.fcmToken,
|
150 | createTime: (_a = oldDetails.createTime) !== null && _a !== void 0 ? _a : Date.now(),
|
151 | subscriptionOptions: {
|
152 | auth: oldDetails.auth,
|
153 | p256dh: oldDetails.p256dh,
|
154 | endpoint: oldDetails.endpoint,
|
155 | swScope: oldDetails.swScope,
|
156 | vapidKey: typeof oldDetails.vapidKey === 'string'
|
157 | ? oldDetails.vapidKey
|
158 | : arrayToBase64(oldDetails.vapidKey)
|
159 | }
|
160 | };
|
161 | }
|
162 | else if (db.oldVersion === 3) {
|
163 | const oldDetails = value;
|
164 | tokenDetails = {
|
165 | token: oldDetails.fcmToken,
|
166 | createTime: oldDetails.createTime,
|
167 | subscriptionOptions: {
|
168 | auth: arrayToBase64(oldDetails.auth),
|
169 | p256dh: arrayToBase64(oldDetails.p256dh),
|
170 | endpoint: oldDetails.endpoint,
|
171 | swScope: oldDetails.swScope,
|
172 | vapidKey: arrayToBase64(oldDetails.vapidKey)
|
173 | }
|
174 | };
|
175 | }
|
176 | else if (db.oldVersion === 4) {
|
177 | const oldDetails = value;
|
178 | tokenDetails = {
|
179 | token: oldDetails.fcmToken,
|
180 | createTime: oldDetails.createTime,
|
181 | subscriptionOptions: {
|
182 | auth: arrayToBase64(oldDetails.auth),
|
183 | p256dh: arrayToBase64(oldDetails.p256dh),
|
184 | endpoint: oldDetails.endpoint,
|
185 | swScope: oldDetails.swScope,
|
186 | vapidKey: arrayToBase64(oldDetails.vapidKey)
|
187 | }
|
188 | };
|
189 | }
|
190 | });
|
191 | db.close();
|
192 |
|
193 | await deleteDb(OLD_DB_NAME);
|
194 | await deleteDb('fcm_vapid_details_db');
|
195 | await deleteDb('undefined');
|
196 | return checkTokenDetails(tokenDetails) ? tokenDetails : null;
|
197 | }
|
198 | function checkTokenDetails(tokenDetails) {
|
199 | if (!tokenDetails || !tokenDetails.subscriptionOptions) {
|
200 | return false;
|
201 | }
|
202 | const { subscriptionOptions } = tokenDetails;
|
203 | return (typeof tokenDetails.createTime === 'number' &&
|
204 | tokenDetails.createTime > 0 &&
|
205 | typeof tokenDetails.token === 'string' &&
|
206 | tokenDetails.token.length > 0 &&
|
207 | typeof subscriptionOptions.auth === 'string' &&
|
208 | subscriptionOptions.auth.length > 0 &&
|
209 | typeof subscriptionOptions.p256dh === 'string' &&
|
210 | subscriptionOptions.p256dh.length > 0 &&
|
211 | typeof subscriptionOptions.endpoint === 'string' &&
|
212 | subscriptionOptions.endpoint.length > 0 &&
|
213 | typeof subscriptionOptions.swScope === 'string' &&
|
214 | subscriptionOptions.swScope.length > 0 &&
|
215 | typeof subscriptionOptions.vapidKey === 'string' &&
|
216 | subscriptionOptions.vapidKey.length > 0);
|
217 | }
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 |
|
236 | const DATABASE_NAME = 'firebase-messaging-database';
|
237 | const DATABASE_VERSION = 1;
|
238 | const OBJECT_STORE_NAME = 'firebase-messaging-store';
|
239 | let dbPromise = null;
|
240 | function getDbPromise() {
|
241 | if (!dbPromise) {
|
242 | dbPromise = openDb(DATABASE_NAME, DATABASE_VERSION, upgradeDb => {
|
243 |
|
244 |
|
245 |
|
246 |
|
247 | switch (upgradeDb.oldVersion) {
|
248 | case 0:
|
249 | upgradeDb.createObjectStore(OBJECT_STORE_NAME);
|
250 | }
|
251 | });
|
252 | }
|
253 | return dbPromise;
|
254 | }
|
255 |
|
256 | async function dbGet(firebaseDependencies) {
|
257 | const key = getKey(firebaseDependencies);
|
258 | const db = await getDbPromise();
|
259 | const tokenDetails = await db
|
260 | .transaction(OBJECT_STORE_NAME)
|
261 | .objectStore(OBJECT_STORE_NAME)
|
262 | .get(key);
|
263 | if (tokenDetails) {
|
264 | return tokenDetails;
|
265 | }
|
266 | else {
|
267 |
|
268 | const oldTokenDetails = await migrateOldDatabase(firebaseDependencies.appConfig.senderId);
|
269 | if (oldTokenDetails) {
|
270 | await dbSet(firebaseDependencies, oldTokenDetails);
|
271 | return oldTokenDetails;
|
272 | }
|
273 | }
|
274 | }
|
275 |
|
276 | async function dbSet(firebaseDependencies, tokenDetails) {
|
277 | const key = getKey(firebaseDependencies);
|
278 | const db = await getDbPromise();
|
279 | const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
|
280 | await tx.objectStore(OBJECT_STORE_NAME).put(tokenDetails, key);
|
281 | await tx.complete;
|
282 | return tokenDetails;
|
283 | }
|
284 |
|
285 | async function dbRemove(firebaseDependencies) {
|
286 | const key = getKey(firebaseDependencies);
|
287 | const db = await getDbPromise();
|
288 | const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
|
289 | await tx.objectStore(OBJECT_STORE_NAME).delete(key);
|
290 | await tx.complete;
|
291 | }
|
292 | function getKey({ appConfig }) {
|
293 | return appConfig.appId;
|
294 | }
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
306 |
|
307 |
|
308 |
|
309 |
|
310 |
|
311 |
|
312 | const ERROR_MAP = {
|
313 | ["missing-app-config-values" ]: 'Missing App configuration value: "{$valueName}"',
|
314 | ["only-available-in-window" ]: 'This method is available in a Window context.',
|
315 | ["only-available-in-sw" ]: 'This method is available in a service worker context.',
|
316 | ["permission-default" ]: 'The notification permission was not granted and dismissed instead.',
|
317 | ["permission-blocked" ]: 'The notification permission was not granted and blocked instead.',
|
318 | ["unsupported-browser" ]: "This browser doesn't support the API's required to use the firebase SDK.",
|
319 | ["indexed-db-unsupported" ]: "This browser doesn't support indexedDb.open() (ex. Safari iFrame, Firefox Private Browsing, etc)",
|
320 | ["failed-service-worker-registration" ]: 'We are unable to register the default service worker. {$browserErrorMessage}',
|
321 | ["token-subscribe-failed" ]: 'A problem occurred while subscribing the user to FCM: {$errorInfo}',
|
322 | ["token-subscribe-no-token" ]: 'FCM returned no token when subscribing the user to push.',
|
323 | ["token-unsubscribe-failed" ]: 'A problem occurred while unsubscribing the ' +
|
324 | 'user from FCM: {$errorInfo}',
|
325 | ["token-update-failed" ]: 'A problem occurred while updating the user from FCM: {$errorInfo}',
|
326 | ["token-update-no-token" ]: 'FCM returned no token when updating the user to push.',
|
327 | ["use-sw-after-get-token" ]: 'The useServiceWorker() method may only be called once and must be ' +
|
328 | 'called before calling getToken() to ensure your service worker is used.',
|
329 | ["invalid-sw-registration" ]: 'The input to useServiceWorker() must be a ServiceWorkerRegistration.',
|
330 | ["invalid-bg-handler" ]: 'The input to setBackgroundMessageHandler() must be a function.',
|
331 | ["invalid-vapid-key" ]: 'The public VAPID key must be a string.',
|
332 | ["use-vapid-key-after-get-token" ]: 'The usePublicVapidKey() method may only be called once and must be ' +
|
333 | 'called before calling getToken() to ensure your VAPID key is used.'
|
334 | };
|
335 | const ERROR_FACTORY = new ErrorFactory('messaging', 'Messaging', ERROR_MAP);
|
336 |
|
337 |
|
338 |
|
339 |
|
340 |
|
341 |
|
342 |
|
343 |
|
344 |
|
345 |
|
346 |
|
347 |
|
348 |
|
349 |
|
350 |
|
351 |
|
352 |
|
353 | async function requestGetToken(firebaseDependencies, subscriptionOptions) {
|
354 | const headers = await getHeaders(firebaseDependencies);
|
355 | const body = getBody(subscriptionOptions);
|
356 | const subscribeOptions = {
|
357 | method: 'POST',
|
358 | headers,
|
359 | body: JSON.stringify(body)
|
360 | };
|
361 | let responseData;
|
362 | try {
|
363 | const response = await fetch(getEndpoint(firebaseDependencies.appConfig), subscribeOptions);
|
364 | responseData = await response.json();
|
365 | }
|
366 | catch (err) {
|
367 | throw ERROR_FACTORY.create("token-subscribe-failed" , {
|
368 | errorInfo: err
|
369 | });
|
370 | }
|
371 | if (responseData.error) {
|
372 | const message = responseData.error.message;
|
373 | throw ERROR_FACTORY.create("token-subscribe-failed" , {
|
374 | errorInfo: message
|
375 | });
|
376 | }
|
377 | if (!responseData.token) {
|
378 | throw ERROR_FACTORY.create("token-subscribe-no-token" );
|
379 | }
|
380 | return responseData.token;
|
381 | }
|
382 | async function requestUpdateToken(firebaseDependencies, tokenDetails) {
|
383 | const headers = await getHeaders(firebaseDependencies);
|
384 | const body = getBody(tokenDetails.subscriptionOptions);
|
385 | const updateOptions = {
|
386 | method: 'PATCH',
|
387 | headers,
|
388 | body: JSON.stringify(body)
|
389 | };
|
390 | let responseData;
|
391 | try {
|
392 | const response = await fetch(`${getEndpoint(firebaseDependencies.appConfig)}/${tokenDetails.token}`, updateOptions);
|
393 | responseData = await response.json();
|
394 | }
|
395 | catch (err) {
|
396 | throw ERROR_FACTORY.create("token-update-failed" , {
|
397 | errorInfo: err
|
398 | });
|
399 | }
|
400 | if (responseData.error) {
|
401 | const message = responseData.error.message;
|
402 | throw ERROR_FACTORY.create("token-update-failed" , {
|
403 | errorInfo: message
|
404 | });
|
405 | }
|
406 | if (!responseData.token) {
|
407 | throw ERROR_FACTORY.create("token-update-no-token" );
|
408 | }
|
409 | return responseData.token;
|
410 | }
|
411 | async function requestDeleteToken(firebaseDependencies, token) {
|
412 | const headers = await getHeaders(firebaseDependencies);
|
413 | const unsubscribeOptions = {
|
414 | method: 'DELETE',
|
415 | headers
|
416 | };
|
417 | try {
|
418 | const response = await fetch(`${getEndpoint(firebaseDependencies.appConfig)}/${token}`, unsubscribeOptions);
|
419 | const responseData = await response.json();
|
420 | if (responseData.error) {
|
421 | const message = responseData.error.message;
|
422 | throw ERROR_FACTORY.create("token-unsubscribe-failed" , {
|
423 | errorInfo: message
|
424 | });
|
425 | }
|
426 | }
|
427 | catch (err) {
|
428 | throw ERROR_FACTORY.create("token-unsubscribe-failed" , {
|
429 | errorInfo: err
|
430 | });
|
431 | }
|
432 | }
|
433 | function getEndpoint({ projectId }) {
|
434 | return `${ENDPOINT}/projects/${projectId}/registrations`;
|
435 | }
|
436 | async function getHeaders({ appConfig, installations }) {
|
437 | const authToken = await installations.getToken();
|
438 | return new Headers({
|
439 | 'Content-Type': 'application/json',
|
440 | Accept: 'application/json',
|
441 | 'x-goog-api-key': appConfig.apiKey,
|
442 | 'x-goog-firebase-installations-auth': `FIS ${authToken}`
|
443 | });
|
444 | }
|
445 | function getBody({ p256dh, auth, endpoint, vapidKey }) {
|
446 | const body = {
|
447 | web: {
|
448 | endpoint,
|
449 | auth,
|
450 | p256dh
|
451 | }
|
452 | };
|
453 | if (vapidKey !== DEFAULT_VAPID_KEY) {
|
454 | body.web.applicationPubKey = vapidKey;
|
455 | }
|
456 | return body;
|
457 | }
|
458 |
|
459 |
|
460 |
|
461 |
|
462 |
|
463 |
|
464 |
|
465 |
|
466 |
|
467 |
|
468 |
|
469 |
|
470 |
|
471 |
|
472 |
|
473 |
|
474 |
|
475 |
|
476 | const TOKEN_EXPIRATION_MS = 7 * 24 * 60 * 60 * 1000;
|
477 | async function getTokenInternal(messaging) {
|
478 | const pushSubscription = await getPushSubscription(messaging.swRegistration, messaging.vapidKey);
|
479 | const subscriptionOptions = {
|
480 | vapidKey: messaging.vapidKey,
|
481 | swScope: messaging.swRegistration.scope,
|
482 | endpoint: pushSubscription.endpoint,
|
483 | auth: arrayToBase64(pushSubscription.getKey('auth')),
|
484 | p256dh: arrayToBase64(pushSubscription.getKey('p256dh'))
|
485 | };
|
486 | const tokenDetails = await dbGet(messaging.firebaseDependencies);
|
487 | if (!tokenDetails) {
|
488 |
|
489 | return getNewToken(messaging.firebaseDependencies, subscriptionOptions);
|
490 | }
|
491 | else if (!isTokenValid(tokenDetails.subscriptionOptions, subscriptionOptions)) {
|
492 |
|
493 | try {
|
494 | await requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);
|
495 | }
|
496 | catch (e) {
|
497 |
|
498 | console.warn(e);
|
499 | }
|
500 | return getNewToken(messaging.firebaseDependencies, subscriptionOptions);
|
501 | }
|
502 | else if (Date.now() >= tokenDetails.createTime + TOKEN_EXPIRATION_MS) {
|
503 |
|
504 | return updateToken(messaging, {
|
505 | token: tokenDetails.token,
|
506 | createTime: Date.now(),
|
507 | subscriptionOptions
|
508 | });
|
509 | }
|
510 | else {
|
511 |
|
512 | return tokenDetails.token;
|
513 | }
|
514 | }
|
515 |
|
516 |
|
517 |
|
518 |
|
519 | async function deleteTokenInternal(messaging) {
|
520 | const tokenDetails = await dbGet(messaging.firebaseDependencies);
|
521 | if (tokenDetails) {
|
522 | await requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);
|
523 | await dbRemove(messaging.firebaseDependencies);
|
524 | }
|
525 |
|
526 | const pushSubscription = await messaging.swRegistration.pushManager.getSubscription();
|
527 | if (pushSubscription) {
|
528 | return pushSubscription.unsubscribe();
|
529 | }
|
530 |
|
531 | return true;
|
532 | }
|
533 | async function updateToken(messaging, tokenDetails) {
|
534 | try {
|
535 | const updatedToken = await requestUpdateToken(messaging.firebaseDependencies, tokenDetails);
|
536 | const updatedTokenDetails = Object.assign(Object.assign({}, tokenDetails), { token: updatedToken, createTime: Date.now() });
|
537 | await dbSet(messaging.firebaseDependencies, updatedTokenDetails);
|
538 | return updatedToken;
|
539 | }
|
540 | catch (e) {
|
541 | await deleteTokenInternal(messaging);
|
542 | throw e;
|
543 | }
|
544 | }
|
545 | async function getNewToken(firebaseDependencies, subscriptionOptions) {
|
546 | const token = await requestGetToken(firebaseDependencies, subscriptionOptions);
|
547 | const tokenDetails = {
|
548 | token,
|
549 | createTime: Date.now(),
|
550 | subscriptionOptions
|
551 | };
|
552 | await dbSet(firebaseDependencies, tokenDetails);
|
553 | return tokenDetails.token;
|
554 | }
|
555 |
|
556 |
|
557 |
|
558 | async function getPushSubscription(swRegistration, vapidKey) {
|
559 | const subscription = await swRegistration.pushManager.getSubscription();
|
560 | if (subscription) {
|
561 | return subscription;
|
562 | }
|
563 | return swRegistration.pushManager.subscribe({
|
564 | userVisibleOnly: true,
|
565 |
|
566 |
|
567 | applicationServerKey: base64ToArray(vapidKey)
|
568 | });
|
569 | }
|
570 |
|
571 |
|
572 |
|
573 | function isTokenValid(dbOptions, currentOptions) {
|
574 | const isVapidKeyEqual = currentOptions.vapidKey === dbOptions.vapidKey;
|
575 | const isEndpointEqual = currentOptions.endpoint === dbOptions.endpoint;
|
576 | const isAuthEqual = currentOptions.auth === dbOptions.auth;
|
577 | const isP256dhEqual = currentOptions.p256dh === dbOptions.p256dh;
|
578 | return isVapidKeyEqual && isEndpointEqual && isAuthEqual && isP256dhEqual;
|
579 | }
|
580 |
|
581 |
|
582 |
|
583 |
|
584 |
|
585 |
|
586 |
|
587 |
|
588 |
|
589 |
|
590 |
|
591 |
|
592 |
|
593 |
|
594 |
|
595 |
|
596 |
|
597 | function externalizePayload(internalPayload) {
|
598 | const payload = {
|
599 | from: internalPayload.from,
|
600 |
|
601 | collapseKey: internalPayload.collapse_key,
|
602 |
|
603 | messageId: internalPayload.fcm_message_id
|
604 | };
|
605 | propagateNotificationPayload(payload, internalPayload);
|
606 | propagateDataPayload(payload, internalPayload);
|
607 | propagateFcmOptions(payload, internalPayload);
|
608 | return payload;
|
609 | }
|
610 | function propagateNotificationPayload(payload, messagePayloadInternal) {
|
611 | if (!messagePayloadInternal.notification) {
|
612 | return;
|
613 | }
|
614 | payload.notification = {};
|
615 | const title = messagePayloadInternal.notification.title;
|
616 | if (!!title) {
|
617 | payload.notification.title = title;
|
618 | }
|
619 | const body = messagePayloadInternal.notification.body;
|
620 | if (!!body) {
|
621 | payload.notification.body = body;
|
622 | }
|
623 | const image = messagePayloadInternal.notification.image;
|
624 | if (!!image) {
|
625 | payload.notification.image = image;
|
626 | }
|
627 | }
|
628 | function propagateDataPayload(payload, messagePayloadInternal) {
|
629 | if (!messagePayloadInternal.data) {
|
630 | return;
|
631 | }
|
632 | payload.data = messagePayloadInternal.data;
|
633 | }
|
634 | function propagateFcmOptions(payload, messagePayloadInternal) {
|
635 | if (!messagePayloadInternal.fcmOptions) {
|
636 | return;
|
637 | }
|
638 | payload.fcmOptions = {};
|
639 | const link = messagePayloadInternal.fcmOptions.link;
|
640 | if (!!link) {
|
641 | payload.fcmOptions.link = link;
|
642 | }
|
643 |
|
644 | const analyticsLabel = messagePayloadInternal.fcmOptions.analytics_label;
|
645 | if (!!analyticsLabel) {
|
646 | payload.fcmOptions.analyticsLabel = analyticsLabel;
|
647 | }
|
648 | }
|
649 |
|
650 |
|
651 |
|
652 |
|
653 |
|
654 |
|
655 |
|
656 |
|
657 |
|
658 |
|
659 |
|
660 |
|
661 |
|
662 |
|
663 |
|
664 |
|
665 |
|
666 | function isConsoleMessage(data) {
|
667 |
|
668 | return typeof data === 'object' && !!data && CONSOLE_CAMPAIGN_ID in data;
|
669 | }
|
670 |
|
671 |
|
672 |
|
673 |
|
674 |
|
675 |
|
676 |
|
677 |
|
678 |
|
679 |
|
680 |
|
681 |
|
682 |
|
683 |
|
684 |
|
685 |
|
686 |
|
687 |
|
688 | function sleep(ms) {
|
689 | return new Promise(resolve => {
|
690 | setTimeout(resolve, ms);
|
691 | });
|
692 | }
|
693 |
|
694 |
|
695 |
|
696 |
|
697 |
|
698 |
|
699 |
|
700 |
|
701 |
|
702 |
|
703 |
|
704 |
|
705 |
|
706 |
|
707 |
|
708 |
|
709 |
|
710 | _mergeStrings('hts/frbslgigp.ogepscmv/ieo/eaylg', 'tp:/ieaeogn-agolai.o/1frlglgc/o');
|
711 | _mergeStrings('AzSCbw63g1R0nCw85jG8', 'Iaya3yLKwmgvh7cF0q4');
|
712 | async function stageLog(messaging, internalPayload) {
|
713 | const fcmEvent = createFcmEvent(internalPayload, await messaging.firebaseDependencies.installations.getId());
|
714 | createAndEnqueueLogEvent(messaging, fcmEvent);
|
715 | }
|
716 | function createFcmEvent(internalPayload, fid) {
|
717 | var _a, _b;
|
718 | const fcmEvent = {};
|
719 |
|
720 |
|
721 | if (!!internalPayload.from) {
|
722 | fcmEvent.project_number = internalPayload.from;
|
723 | }
|
724 | if (!!internalPayload.fcm_message_id) {
|
725 | fcmEvent.message_id = internalPayload.fcm_message_id;
|
726 | }
|
727 | fcmEvent.instance_id = fid;
|
728 | if (!!internalPayload.notification) {
|
729 | fcmEvent.message_type = MessageType$1.DISPLAY_NOTIFICATION.toString();
|
730 | }
|
731 | else {
|
732 | fcmEvent.message_type = MessageType$1.DATA_MESSAGE.toString();
|
733 | }
|
734 | fcmEvent.sdk_platform = SDK_PLATFORM_WEB.toString();
|
735 | fcmEvent.package_name = self.origin.replace(/(^\w+:|^)\/\//, '');
|
736 | if (!!internalPayload.collapse_key) {
|
737 | fcmEvent.collapse_key = internalPayload.collapse_key;
|
738 | }
|
739 | fcmEvent.event = EVENT_MESSAGE_DELIVERED.toString();
|
740 | if (!!((_a = internalPayload.fcmOptions) === null || _a === void 0 ? void 0 : _a.analytics_label)) {
|
741 | fcmEvent.analytics_label = (_b = internalPayload.fcmOptions) === null || _b === void 0 ? void 0 : _b.analytics_label;
|
742 | }
|
743 |
|
744 | return fcmEvent;
|
745 | }
|
746 | function createAndEnqueueLogEvent(messaging, fcmEvent) {
|
747 | const logEvent = {};
|
748 |
|
749 | logEvent.event_time_ms = Math.floor(Date.now()).toString();
|
750 | logEvent.source_extension_json_proto3 = JSON.stringify(fcmEvent);
|
751 |
|
752 | messaging.logEvents.push(logEvent);
|
753 | }
|
754 | function _mergeStrings(s1, s2) {
|
755 | const resultArray = [];
|
756 | for (let i = 0; i < s1.length; i++) {
|
757 | resultArray.push(s1.charAt(i));
|
758 | if (i < s2.length) {
|
759 | resultArray.push(s2.charAt(i));
|
760 | }
|
761 | }
|
762 | return resultArray.join('');
|
763 | }
|
764 |
|
765 |
|
766 |
|
767 |
|
768 |
|
769 |
|
770 |
|
771 |
|
772 |
|
773 |
|
774 |
|
775 |
|
776 |
|
777 |
|
778 |
|
779 |
|
780 |
|
781 | async function onSubChange(event, messaging) {
|
782 | var _a, _b;
|
783 | const { newSubscription } = event;
|
784 | if (!newSubscription) {
|
785 |
|
786 | await deleteTokenInternal(messaging);
|
787 | return;
|
788 | }
|
789 | const tokenDetails = await dbGet(messaging.firebaseDependencies);
|
790 | await deleteTokenInternal(messaging);
|
791 | messaging.vapidKey =
|
792 | (_b = (_a = tokenDetails === null || tokenDetails === void 0 ? void 0 : tokenDetails.subscriptionOptions) === null || _a === void 0 ? void 0 : _a.vapidKey) !== null && _b !== void 0 ? _b : DEFAULT_VAPID_KEY;
|
793 | await getTokenInternal(messaging);
|
794 | }
|
795 | async function onPush(event, messaging) {
|
796 | const internalPayload = getMessagePayloadInternal(event);
|
797 | if (!internalPayload) {
|
798 |
|
799 | return;
|
800 | }
|
801 |
|
802 | if (messaging.deliveryMetricsExportedToBigQueryEnabled) {
|
803 | await stageLog(messaging, internalPayload);
|
804 | }
|
805 |
|
806 | const clientList = await getClientList();
|
807 | if (hasVisibleClients(clientList)) {
|
808 | return sendMessagePayloadInternalToWindows(clientList, internalPayload);
|
809 | }
|
810 |
|
811 | if (!!internalPayload.notification) {
|
812 | await showNotification(wrapInternalPayload(internalPayload));
|
813 | }
|
814 | if (!messaging) {
|
815 | return;
|
816 | }
|
817 | if (!!messaging.onBackgroundMessageHandler) {
|
818 | const payload = externalizePayload(internalPayload);
|
819 | if (typeof messaging.onBackgroundMessageHandler === 'function') {
|
820 | messaging.onBackgroundMessageHandler(payload);
|
821 | }
|
822 | else {
|
823 | messaging.onBackgroundMessageHandler.next(payload);
|
824 | }
|
825 | }
|
826 | }
|
827 | async function onNotificationClick(event) {
|
828 | var _a, _b;
|
829 | const internalPayload = (_b = (_a = event.notification) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b[FCM_MSG];
|
830 | if (!internalPayload) {
|
831 | return;
|
832 | }
|
833 | else if (event.action) {
|
834 |
|
835 |
|
836 | return;
|
837 | }
|
838 |
|
839 | event.stopImmediatePropagation();
|
840 | event.notification.close();
|
841 |
|
842 | const link = getLink(internalPayload);
|
843 | if (!link) {
|
844 | return;
|
845 | }
|
846 |
|
847 | const url = new URL(link, self.location.href);
|
848 | const originUrl = new URL(self.location.origin);
|
849 | if (url.host !== originUrl.host) {
|
850 | return;
|
851 | }
|
852 | let client = await getWindowClient(url);
|
853 | if (!client) {
|
854 | client = await self.clients.openWindow(link);
|
855 |
|
856 |
|
857 | await sleep(3000);
|
858 | }
|
859 | else {
|
860 | client = await client.focus();
|
861 | }
|
862 | if (!client) {
|
863 |
|
864 | return;
|
865 | }
|
866 | internalPayload.messageType = MessageType.NOTIFICATION_CLICKED;
|
867 | internalPayload.isFirebaseMessaging = true;
|
868 | return client.postMessage(internalPayload);
|
869 | }
|
870 | function wrapInternalPayload(internalPayload) {
|
871 | const wrappedInternalPayload = Object.assign({}, internalPayload.notification);
|
872 |
|
873 |
|
874 |
|
875 | wrappedInternalPayload.data = {
|
876 | [FCM_MSG]: internalPayload
|
877 | };
|
878 | return wrappedInternalPayload;
|
879 | }
|
880 | function getMessagePayloadInternal({ data }) {
|
881 | if (!data) {
|
882 | return null;
|
883 | }
|
884 | try {
|
885 | return data.json();
|
886 | }
|
887 | catch (err) {
|
888 |
|
889 | return null;
|
890 | }
|
891 | }
|
892 |
|
893 |
|
894 |
|
895 |
|
896 | async function getWindowClient(url) {
|
897 | const clientList = await getClientList();
|
898 | for (const client of clientList) {
|
899 | const clientUrl = new URL(client.url, self.location.href);
|
900 | if (url.host === clientUrl.host) {
|
901 | return client;
|
902 | }
|
903 | }
|
904 | return null;
|
905 | }
|
906 |
|
907 |
|
908 |
|
909 |
|
910 | function hasVisibleClients(clientList) {
|
911 | return clientList.some(client => client.visibilityState === 'visible' &&
|
912 |
|
913 |
|
914 | !client.url.startsWith('chrome-extension://'));
|
915 | }
|
916 | function sendMessagePayloadInternalToWindows(clientList, internalPayload) {
|
917 | internalPayload.isFirebaseMessaging = true;
|
918 | internalPayload.messageType = MessageType.PUSH_RECEIVED;
|
919 | for (const client of clientList) {
|
920 | client.postMessage(internalPayload);
|
921 | }
|
922 | }
|
923 | function getClientList() {
|
924 | return self.clients.matchAll({
|
925 | type: 'window',
|
926 | includeUncontrolled: true
|
927 |
|
928 | });
|
929 | }
|
930 | function showNotification(notificationPayloadInternal) {
|
931 | var _a;
|
932 |
|
933 |
|
934 | const { actions } = notificationPayloadInternal;
|
935 | const { maxActions } = Notification;
|
936 | if (actions && maxActions && actions.length > maxActions) {
|
937 | console.warn(`This browser only supports ${maxActions} actions. The remaining actions will not be displayed.`);
|
938 | }
|
939 | return self.registration.showNotification(
|
940 | (_a = notificationPayloadInternal.title) !== null && _a !== void 0 ? _a : '', notificationPayloadInternal);
|
941 | }
|
942 | function getLink(payload) {
|
943 | var _a, _b, _c;
|
944 |
|
945 | const link = (_b = (_a = payload.fcmOptions) === null || _a === void 0 ? void 0 : _a.link) !== null && _b !== void 0 ? _b : (_c = payload.notification) === null || _c === void 0 ? void 0 : _c.click_action;
|
946 | if (link) {
|
947 | return link;
|
948 | }
|
949 | if (isConsoleMessage(payload.data)) {
|
950 |
|
951 | return self.location.origin;
|
952 | }
|
953 | else {
|
954 | return null;
|
955 | }
|
956 | }
|
957 |
|
958 |
|
959 |
|
960 |
|
961 |
|
962 |
|
963 |
|
964 |
|
965 |
|
966 |
|
967 |
|
968 |
|
969 |
|
970 |
|
971 |
|
972 |
|
973 |
|
974 | function extractAppConfig(app) {
|
975 | if (!app || !app.options) {
|
976 | throw getMissingValueError('App Configuration Object');
|
977 | }
|
978 | if (!app.name) {
|
979 | throw getMissingValueError('App Name');
|
980 | }
|
981 |
|
982 | const configKeys = [
|
983 | 'projectId',
|
984 | 'apiKey',
|
985 | 'appId',
|
986 | 'messagingSenderId'
|
987 | ];
|
988 | const { options } = app;
|
989 | for (const keyName of configKeys) {
|
990 | if (!options[keyName]) {
|
991 | throw getMissingValueError(keyName);
|
992 | }
|
993 | }
|
994 | return {
|
995 | appName: app.name,
|
996 | projectId: options.projectId,
|
997 | apiKey: options.apiKey,
|
998 | appId: options.appId,
|
999 | senderId: options.messagingSenderId
|
1000 | };
|
1001 | }
|
1002 | function getMissingValueError(valueName) {
|
1003 | return ERROR_FACTORY.create("missing-app-config-values" , {
|
1004 | valueName
|
1005 | });
|
1006 | }
|
1007 |
|
1008 |
|
1009 |
|
1010 |
|
1011 |
|
1012 |
|
1013 |
|
1014 |
|
1015 |
|
1016 |
|
1017 |
|
1018 |
|
1019 |
|
1020 |
|
1021 |
|
1022 |
|
1023 |
|
1024 | class MessagingService {
|
1025 | constructor(app, installations, analyticsProvider) {
|
1026 |
|
1027 | this.deliveryMetricsExportedToBigQueryEnabled = false;
|
1028 | this.onBackgroundMessageHandler = null;
|
1029 | this.onMessageHandler = null;
|
1030 | this.logEvents = [];
|
1031 | this.isLogServiceStarted = false;
|
1032 | const appConfig = extractAppConfig(app);
|
1033 | this.firebaseDependencies = {
|
1034 | app,
|
1035 | appConfig,
|
1036 | installations,
|
1037 | analyticsProvider
|
1038 | };
|
1039 | }
|
1040 | _delete() {
|
1041 | return Promise.resolve();
|
1042 | }
|
1043 | }
|
1044 |
|
1045 |
|
1046 |
|
1047 |
|
1048 |
|
1049 |
|
1050 |
|
1051 |
|
1052 |
|
1053 |
|
1054 |
|
1055 |
|
1056 |
|
1057 |
|
1058 |
|
1059 |
|
1060 |
|
1061 | const SwMessagingFactory = (container) => {
|
1062 | const messaging = new MessagingService(container.getProvider('app').getImmediate(), container.getProvider('installations-internal').getImmediate(), container.getProvider('analytics-internal'));
|
1063 | self.addEventListener('push', e => {
|
1064 | e.waitUntil(onPush(e, messaging));
|
1065 | });
|
1066 | self.addEventListener('pushsubscriptionchange', e => {
|
1067 | e.waitUntil(onSubChange(e, messaging));
|
1068 | });
|
1069 | self.addEventListener('notificationclick', e => {
|
1070 | e.waitUntil(onNotificationClick(e));
|
1071 | });
|
1072 | return messaging;
|
1073 | };
|
1074 |
|
1075 |
|
1076 |
|
1077 |
|
1078 |
|
1079 | function registerMessagingInSw() {
|
1080 | _registerComponent(new Component('messaging-sw', SwMessagingFactory, "PUBLIC" ));
|
1081 | }
|
1082 |
|
1083 |
|
1084 |
|
1085 |
|
1086 |
|
1087 |
|
1088 |
|
1089 |
|
1090 |
|
1091 |
|
1092 |
|
1093 |
|
1094 |
|
1095 |
|
1096 |
|
1097 |
|
1098 |
|
1099 |
|
1100 |
|
1101 |
|
1102 |
|
1103 |
|
1104 |
|
1105 | async function isSwSupported() {
|
1106 |
|
1107 |
|
1108 |
|
1109 | return (isIndexedDBAvailable() &&
|
1110 | (await validateIndexedDBOpenable()) &&
|
1111 | 'PushManager' in self &&
|
1112 | 'Notification' in self &&
|
1113 | ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&
|
1114 | PushSubscription.prototype.hasOwnProperty('getKey'));
|
1115 | }
|
1116 |
|
1117 |
|
1118 |
|
1119 |
|
1120 |
|
1121 |
|
1122 |
|
1123 |
|
1124 |
|
1125 |
|
1126 |
|
1127 |
|
1128 |
|
1129 |
|
1130 |
|
1131 |
|
1132 |
|
1133 | function onBackgroundMessage$1(messaging, nextOrObserver) {
|
1134 | if (self.document !== undefined) {
|
1135 | throw ERROR_FACTORY.create("only-available-in-sw" );
|
1136 | }
|
1137 | messaging.onBackgroundMessageHandler = nextOrObserver;
|
1138 | return () => {
|
1139 | messaging.onBackgroundMessageHandler = null;
|
1140 | };
|
1141 | }
|
1142 |
|
1143 |
|
1144 |
|
1145 |
|
1146 |
|
1147 |
|
1148 |
|
1149 |
|
1150 |
|
1151 |
|
1152 |
|
1153 |
|
1154 |
|
1155 |
|
1156 |
|
1157 |
|
1158 |
|
1159 | function _setDeliveryMetricsExportedToBigQueryEnabled(messaging, enable) {
|
1160 | messaging.deliveryMetricsExportedToBigQueryEnabled =
|
1161 | enable;
|
1162 | }
|
1163 |
|
1164 |
|
1165 |
|
1166 |
|
1167 |
|
1168 |
|
1169 |
|
1170 |
|
1171 |
|
1172 |
|
1173 |
|
1174 |
|
1175 |
|
1176 |
|
1177 |
|
1178 |
|
1179 |
|
1180 |
|
1181 |
|
1182 |
|
1183 |
|
1184 |
|
1185 |
|
1186 |
|
1187 | function getMessagingInSw(app = getApp()) {
|
1188 |
|
1189 |
|
1190 |
|
1191 |
|
1192 | isSwSupported().then(isSupported => {
|
1193 |
|
1194 | if (!isSupported) {
|
1195 | throw ERROR_FACTORY.create("unsupported-browser" );
|
1196 | }
|
1197 | }, _ => {
|
1198 |
|
1199 | throw ERROR_FACTORY.create("indexed-db-unsupported" );
|
1200 | });
|
1201 | return _getProvider(getModularInstance(app), 'messaging-sw').getImmediate();
|
1202 | }
|
1203 |
|
1204 |
|
1205 |
|
1206 |
|
1207 |
|
1208 |
|
1209 |
|
1210 |
|
1211 |
|
1212 |
|
1213 |
|
1214 |
|
1215 | function onBackgroundMessage(messaging, nextOrObserver) {
|
1216 | messaging = getModularInstance(messaging);
|
1217 | return onBackgroundMessage$1(messaging, nextOrObserver);
|
1218 | }
|
1219 |
|
1220 |
|
1221 |
|
1222 |
|
1223 |
|
1224 |
|
1225 |
|
1226 |
|
1227 |
|
1228 |
|
1229 |
|
1230 | function experimentalSetDeliveryMetricsExportedToBigQueryEnabled(messaging, enable) {
|
1231 | messaging = getModularInstance(messaging);
|
1232 | return _setDeliveryMetricsExportedToBigQueryEnabled(messaging, enable);
|
1233 | }
|
1234 |
|
1235 |
|
1236 |
|
1237 |
|
1238 |
|
1239 |
|
1240 |
|
1241 |
|
1242 |
|
1243 |
|
1244 |
|
1245 |
|
1246 |
|
1247 |
|
1248 |
|
1249 |
|
1250 |
|
1251 | registerMessagingInSw();
|
1252 |
|
1253 | export { experimentalSetDeliveryMetricsExportedToBigQueryEnabled, getMessagingInSw as getMessaging, isSwSupported as isSupported, onBackgroundMessage };
|
1254 |
|