1433 lines
58 KiB
JavaScript
1433 lines
58 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||
|
|
||
|
var app = require('@firebase/app');
|
||
|
var component = require('@firebase/component');
|
||
|
var tslib = require('tslib');
|
||
|
var util = require('@firebase/util');
|
||
|
var idb = require('idb');
|
||
|
|
||
|
var name = "@firebase/installations";
|
||
|
var version = "0.6.5";
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
var PENDING_TIMEOUT_MS = 10000;
|
||
|
var PACKAGE_VERSION = "w:".concat(version);
|
||
|
var INTERNAL_AUTH_VERSION = 'FIS_v2';
|
||
|
var INSTALLATIONS_API_URL = 'https://firebaseinstallations.googleapis.com/v1';
|
||
|
var TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour
|
||
|
var SERVICE = 'installations';
|
||
|
var SERVICE_NAME = 'Installations';
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
var _a;
|
||
|
var ERROR_DESCRIPTION_MAP = (_a = {},
|
||
|
_a["missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */] = 'Missing App configuration value: "{$valueName}"',
|
||
|
_a["not-registered" /* ErrorCode.NOT_REGISTERED */] = 'Firebase Installation is not registered.',
|
||
|
_a["installation-not-found" /* ErrorCode.INSTALLATION_NOT_FOUND */] = 'Firebase Installation not found.',
|
||
|
_a["request-failed" /* ErrorCode.REQUEST_FAILED */] = '{$requestName} request failed with error "{$serverCode} {$serverStatus}: {$serverMessage}"',
|
||
|
_a["app-offline" /* ErrorCode.APP_OFFLINE */] = 'Could not process request. Application offline.',
|
||
|
_a["delete-pending-registration" /* ErrorCode.DELETE_PENDING_REGISTRATION */] = "Can't delete installation while there is a pending registration request.",
|
||
|
_a);
|
||
|
var ERROR_FACTORY = new util.ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP);
|
||
|
/** Returns true if error is a FirebaseError that is based on an error from the server. */
|
||
|
function isServerError(error) {
|
||
|
return (error instanceof util.FirebaseError &&
|
||
|
error.code.includes("request-failed" /* ErrorCode.REQUEST_FAILED */));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
function getInstallationsEndpoint(_a) {
|
||
|
var projectId = _a.projectId;
|
||
|
return "".concat(INSTALLATIONS_API_URL, "/projects/").concat(projectId, "/installations");
|
||
|
}
|
||
|
function extractAuthTokenInfoFromResponse(response) {
|
||
|
return {
|
||
|
token: response.token,
|
||
|
requestStatus: 2 /* RequestStatus.COMPLETED */,
|
||
|
expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),
|
||
|
creationTime: Date.now()
|
||
|
};
|
||
|
}
|
||
|
function getErrorFromResponse(requestName, response) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var responseJson, errorData;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0: return [4 /*yield*/, response.json()];
|
||
|
case 1:
|
||
|
responseJson = _a.sent();
|
||
|
errorData = responseJson.error;
|
||
|
return [2 /*return*/, ERROR_FACTORY.create("request-failed" /* ErrorCode.REQUEST_FAILED */, {
|
||
|
requestName: requestName,
|
||
|
serverCode: errorData.code,
|
||
|
serverMessage: errorData.message,
|
||
|
serverStatus: errorData.status
|
||
|
})];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
function getHeaders(_a) {
|
||
|
var apiKey = _a.apiKey;
|
||
|
return new Headers({
|
||
|
'Content-Type': 'application/json',
|
||
|
Accept: 'application/json',
|
||
|
'x-goog-api-key': apiKey
|
||
|
});
|
||
|
}
|
||
|
function getHeadersWithAuth(appConfig, _a) {
|
||
|
var refreshToken = _a.refreshToken;
|
||
|
var headers = getHeaders(appConfig);
|
||
|
headers.append('Authorization', getAuthorizationHeader(refreshToken));
|
||
|
return headers;
|
||
|
}
|
||
|
/**
|
||
|
* Calls the passed in fetch wrapper and returns the response.
|
||
|
* If the returned response has a status of 5xx, re-runs the function once and
|
||
|
* returns the response.
|
||
|
*/
|
||
|
function retryIfServerError(fn) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var result;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0: return [4 /*yield*/, fn()];
|
||
|
case 1:
|
||
|
result = _a.sent();
|
||
|
if (result.status >= 500 && result.status < 600) {
|
||
|
// Internal Server Error. Retry request.
|
||
|
return [2 /*return*/, fn()];
|
||
|
}
|
||
|
return [2 /*return*/, result];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
function getExpiresInFromResponseExpiresIn(responseExpiresIn) {
|
||
|
// This works because the server will never respond with fractions of a second.
|
||
|
return Number(responseExpiresIn.replace('s', '000'));
|
||
|
}
|
||
|
function getAuthorizationHeader(refreshToken) {
|
||
|
return "".concat(INTERNAL_AUTH_VERSION, " ").concat(refreshToken);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
function createInstallationRequest(_a, _b) {
|
||
|
var appConfig = _a.appConfig, heartbeatServiceProvider = _a.heartbeatServiceProvider;
|
||
|
var fid = _b.fid;
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var endpoint, headers, heartbeatService, heartbeatsHeader, body, request, response, responseValue, registeredInstallationEntry;
|
||
|
return tslib.__generator(this, function (_c) {
|
||
|
switch (_c.label) {
|
||
|
case 0:
|
||
|
endpoint = getInstallationsEndpoint(appConfig);
|
||
|
headers = getHeaders(appConfig);
|
||
|
heartbeatService = heartbeatServiceProvider.getImmediate({
|
||
|
optional: true
|
||
|
});
|
||
|
if (!heartbeatService) return [3 /*break*/, 2];
|
||
|
return [4 /*yield*/, heartbeatService.getHeartbeatsHeader()];
|
||
|
case 1:
|
||
|
heartbeatsHeader = _c.sent();
|
||
|
if (heartbeatsHeader) {
|
||
|
headers.append('x-firebase-client', heartbeatsHeader);
|
||
|
}
|
||
|
_c.label = 2;
|
||
|
case 2:
|
||
|
body = {
|
||
|
fid: fid,
|
||
|
authVersion: INTERNAL_AUTH_VERSION,
|
||
|
appId: appConfig.appId,
|
||
|
sdkVersion: PACKAGE_VERSION
|
||
|
};
|
||
|
request = {
|
||
|
method: 'POST',
|
||
|
headers: headers,
|
||
|
body: JSON.stringify(body)
|
||
|
};
|
||
|
return [4 /*yield*/, retryIfServerError(function () { return fetch(endpoint, request); })];
|
||
|
case 3:
|
||
|
response = _c.sent();
|
||
|
if (!response.ok) return [3 /*break*/, 5];
|
||
|
return [4 /*yield*/, response.json()];
|
||
|
case 4:
|
||
|
responseValue = _c.sent();
|
||
|
registeredInstallationEntry = {
|
||
|
fid: responseValue.fid || fid,
|
||
|
registrationStatus: 2 /* RequestStatus.COMPLETED */,
|
||
|
refreshToken: responseValue.refreshToken,
|
||
|
authToken: extractAuthTokenInfoFromResponse(responseValue.authToken)
|
||
|
};
|
||
|
return [2 /*return*/, registeredInstallationEntry];
|
||
|
case 5: return [4 /*yield*/, getErrorFromResponse('Create Installation', response)];
|
||
|
case 6: throw _c.sent();
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/** Returns a promise that resolves after given time passes. */
|
||
|
function sleep(ms) {
|
||
|
return new Promise(function (resolve) {
|
||
|
setTimeout(resolve, ms);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
function bufferToBase64UrlSafe(array) {
|
||
|
var b64 = btoa(String.fromCharCode.apply(String, tslib.__spreadArray([], tslib.__read(array), false)));
|
||
|
return b64.replace(/\+/g, '-').replace(/\//g, '_');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
var VALID_FID_PATTERN = /^[cdef][\w-]{21}$/;
|
||
|
var INVALID_FID = '';
|
||
|
/**
|
||
|
* Generates a new FID using random values from Web Crypto API.
|
||
|
* Returns an empty string if FID generation fails for any reason.
|
||
|
*/
|
||
|
function generateFid() {
|
||
|
try {
|
||
|
// A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5
|
||
|
// bytes. our implementation generates a 17 byte array instead.
|
||
|
var fidByteArray = new Uint8Array(17);
|
||
|
var crypto_1 = self.crypto || self.msCrypto;
|
||
|
crypto_1.getRandomValues(fidByteArray);
|
||
|
// Replace the first 4 random bits with the constant FID header of 0b0111.
|
||
|
fidByteArray[0] = 112 + (fidByteArray[0] % 16);
|
||
|
var fid = encode(fidByteArray);
|
||
|
return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID;
|
||
|
}
|
||
|
catch (_a) {
|
||
|
// FID generation errored
|
||
|
return INVALID_FID;
|
||
|
}
|
||
|
}
|
||
|
/** Converts a FID Uint8Array to a base64 string representation. */
|
||
|
function encode(fidByteArray) {
|
||
|
var b64String = bufferToBase64UrlSafe(fidByteArray);
|
||
|
// Remove the 23rd character that was added because of the extra 4 bits at the
|
||
|
// end of our 17 byte array, and the '=' padding.
|
||
|
return b64String.substr(0, 22);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/** Returns a string key that can be used to identify the app. */
|
||
|
function getKey(appConfig) {
|
||
|
return "".concat(appConfig.appName, "!").concat(appConfig.appId);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
var fidChangeCallbacks = new Map();
|
||
|
/**
|
||
|
* Calls the onIdChange callbacks with the new FID value, and broadcasts the
|
||
|
* change to other tabs.
|
||
|
*/
|
||
|
function fidChanged(appConfig, fid) {
|
||
|
var key = getKey(appConfig);
|
||
|
callFidChangeCallbacks(key, fid);
|
||
|
broadcastFidChange(key, fid);
|
||
|
}
|
||
|
function addCallback(appConfig, callback) {
|
||
|
// Open the broadcast channel if it's not already open,
|
||
|
// to be able to listen to change events from other tabs.
|
||
|
getBroadcastChannel();
|
||
|
var key = getKey(appConfig);
|
||
|
var callbackSet = fidChangeCallbacks.get(key);
|
||
|
if (!callbackSet) {
|
||
|
callbackSet = new Set();
|
||
|
fidChangeCallbacks.set(key, callbackSet);
|
||
|
}
|
||
|
callbackSet.add(callback);
|
||
|
}
|
||
|
function removeCallback(appConfig, callback) {
|
||
|
var key = getKey(appConfig);
|
||
|
var callbackSet = fidChangeCallbacks.get(key);
|
||
|
if (!callbackSet) {
|
||
|
return;
|
||
|
}
|
||
|
callbackSet.delete(callback);
|
||
|
if (callbackSet.size === 0) {
|
||
|
fidChangeCallbacks.delete(key);
|
||
|
}
|
||
|
// Close broadcast channel if there are no more callbacks.
|
||
|
closeBroadcastChannel();
|
||
|
}
|
||
|
function callFidChangeCallbacks(key, fid) {
|
||
|
var e_1, _a;
|
||
|
var callbacks = fidChangeCallbacks.get(key);
|
||
|
if (!callbacks) {
|
||
|
return;
|
||
|
}
|
||
|
try {
|
||
|
for (var callbacks_1 = tslib.__values(callbacks), callbacks_1_1 = callbacks_1.next(); !callbacks_1_1.done; callbacks_1_1 = callbacks_1.next()) {
|
||
|
var callback = callbacks_1_1.value;
|
||
|
callback(fid);
|
||
|
}
|
||
|
}
|
||
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||
|
finally {
|
||
|
try {
|
||
|
if (callbacks_1_1 && !callbacks_1_1.done && (_a = callbacks_1.return)) _a.call(callbacks_1);
|
||
|
}
|
||
|
finally { if (e_1) throw e_1.error; }
|
||
|
}
|
||
|
}
|
||
|
function broadcastFidChange(key, fid) {
|
||
|
var channel = getBroadcastChannel();
|
||
|
if (channel) {
|
||
|
channel.postMessage({ key: key, fid: fid });
|
||
|
}
|
||
|
closeBroadcastChannel();
|
||
|
}
|
||
|
var broadcastChannel = null;
|
||
|
/** Opens and returns a BroadcastChannel if it is supported by the browser. */
|
||
|
function getBroadcastChannel() {
|
||
|
if (!broadcastChannel && 'BroadcastChannel' in self) {
|
||
|
broadcastChannel = new BroadcastChannel('[Firebase] FID Change');
|
||
|
broadcastChannel.onmessage = function (e) {
|
||
|
callFidChangeCallbacks(e.data.key, e.data.fid);
|
||
|
};
|
||
|
}
|
||
|
return broadcastChannel;
|
||
|
}
|
||
|
function closeBroadcastChannel() {
|
||
|
if (fidChangeCallbacks.size === 0 && broadcastChannel) {
|
||
|
broadcastChannel.close();
|
||
|
broadcastChannel = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
var DATABASE_NAME = 'firebase-installations-database';
|
||
|
var DATABASE_VERSION = 1;
|
||
|
var OBJECT_STORE_NAME = 'firebase-installations-store';
|
||
|
var dbPromise = null;
|
||
|
function getDbPromise() {
|
||
|
if (!dbPromise) {
|
||
|
dbPromise = idb.openDB(DATABASE_NAME, DATABASE_VERSION, {
|
||
|
upgrade: function (db, oldVersion) {
|
||
|
// We don't use 'break' in this switch statement, the fall-through
|
||
|
// behavior is what we want, because if there are multiple versions between
|
||
|
// the old version and the current version, we want ALL the migrations
|
||
|
// that correspond to those versions to run, not only the last one.
|
||
|
// eslint-disable-next-line default-case
|
||
|
switch (oldVersion) {
|
||
|
case 0:
|
||
|
db.createObjectStore(OBJECT_STORE_NAME);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
return dbPromise;
|
||
|
}
|
||
|
/** Assigns or overwrites the record for the given key with the given value. */
|
||
|
function set(appConfig, value) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var key, db, tx, objectStore, oldValue;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
key = getKey(appConfig);
|
||
|
return [4 /*yield*/, getDbPromise()];
|
||
|
case 1:
|
||
|
db = _a.sent();
|
||
|
tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
|
||
|
objectStore = tx.objectStore(OBJECT_STORE_NAME);
|
||
|
return [4 /*yield*/, objectStore.get(key)];
|
||
|
case 2:
|
||
|
oldValue = (_a.sent());
|
||
|
return [4 /*yield*/, objectStore.put(value, key)];
|
||
|
case 3:
|
||
|
_a.sent();
|
||
|
return [4 /*yield*/, tx.done];
|
||
|
case 4:
|
||
|
_a.sent();
|
||
|
if (!oldValue || oldValue.fid !== value.fid) {
|
||
|
fidChanged(appConfig, value.fid);
|
||
|
}
|
||
|
return [2 /*return*/, value];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
/** Removes record(s) from the objectStore that match the given key. */
|
||
|
function remove(appConfig) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var key, db, tx;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
key = getKey(appConfig);
|
||
|
return [4 /*yield*/, getDbPromise()];
|
||
|
case 1:
|
||
|
db = _a.sent();
|
||
|
tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
|
||
|
return [4 /*yield*/, tx.objectStore(OBJECT_STORE_NAME).delete(key)];
|
||
|
case 2:
|
||
|
_a.sent();
|
||
|
return [4 /*yield*/, tx.done];
|
||
|
case 3:
|
||
|
_a.sent();
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
/**
|
||
|
* Atomically updates a record with the result of updateFn, which gets
|
||
|
* called with the current value. If newValue is undefined, the record is
|
||
|
* deleted instead.
|
||
|
* @return Updated value
|
||
|
*/
|
||
|
function update(appConfig, updateFn) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var key, db, tx, store, oldValue, newValue;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
key = getKey(appConfig);
|
||
|
return [4 /*yield*/, getDbPromise()];
|
||
|
case 1:
|
||
|
db = _a.sent();
|
||
|
tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
|
||
|
store = tx.objectStore(OBJECT_STORE_NAME);
|
||
|
return [4 /*yield*/, store.get(key)];
|
||
|
case 2:
|
||
|
oldValue = (_a.sent());
|
||
|
newValue = updateFn(oldValue);
|
||
|
if (!(newValue === undefined)) return [3 /*break*/, 4];
|
||
|
return [4 /*yield*/, store.delete(key)];
|
||
|
case 3:
|
||
|
_a.sent();
|
||
|
return [3 /*break*/, 6];
|
||
|
case 4: return [4 /*yield*/, store.put(newValue, key)];
|
||
|
case 5:
|
||
|
_a.sent();
|
||
|
_a.label = 6;
|
||
|
case 6: return [4 /*yield*/, tx.done];
|
||
|
case 7:
|
||
|
_a.sent();
|
||
|
if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {
|
||
|
fidChanged(appConfig, newValue.fid);
|
||
|
}
|
||
|
return [2 /*return*/, newValue];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/**
|
||
|
* Updates and returns the InstallationEntry from the database.
|
||
|
* Also triggers a registration request if it is necessary and possible.
|
||
|
*/
|
||
|
function getInstallationEntry(installations) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var registrationPromise, installationEntry;
|
||
|
var _a;
|
||
|
return tslib.__generator(this, function (_b) {
|
||
|
switch (_b.label) {
|
||
|
case 0: return [4 /*yield*/, update(installations.appConfig, function (oldEntry) {
|
||
|
var installationEntry = updateOrCreateInstallationEntry(oldEntry);
|
||
|
var entryWithPromise = triggerRegistrationIfNecessary(installations, installationEntry);
|
||
|
registrationPromise = entryWithPromise.registrationPromise;
|
||
|
return entryWithPromise.installationEntry;
|
||
|
})];
|
||
|
case 1:
|
||
|
installationEntry = _b.sent();
|
||
|
if (!(installationEntry.fid === INVALID_FID)) return [3 /*break*/, 3];
|
||
|
_a = {};
|
||
|
return [4 /*yield*/, registrationPromise];
|
||
|
case 2:
|
||
|
// FID generation failed. Waiting for the FID from the server.
|
||
|
return [2 /*return*/, (_a.installationEntry = _b.sent(), _a)];
|
||
|
case 3: return [2 /*return*/, {
|
||
|
installationEntry: installationEntry,
|
||
|
registrationPromise: registrationPromise
|
||
|
}];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
/**
|
||
|
* Creates a new Installation Entry if one does not exist.
|
||
|
* Also clears timed out pending requests.
|
||
|
*/
|
||
|
function updateOrCreateInstallationEntry(oldEntry) {
|
||
|
var entry = oldEntry || {
|
||
|
fid: generateFid(),
|
||
|
registrationStatus: 0 /* RequestStatus.NOT_STARTED */
|
||
|
};
|
||
|
return clearTimedOutRequest(entry);
|
||
|
}
|
||
|
/**
|
||
|
* If the Firebase Installation is not registered yet, this will trigger the
|
||
|
* registration and return an InProgressInstallationEntry.
|
||
|
*
|
||
|
* If registrationPromise does not exist, the installationEntry is guaranteed
|
||
|
* to be registered.
|
||
|
*/
|
||
|
function triggerRegistrationIfNecessary(installations, installationEntry) {
|
||
|
if (installationEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {
|
||
|
if (!navigator.onLine) {
|
||
|
// Registration required but app is offline.
|
||
|
var registrationPromiseWithError = Promise.reject(ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */));
|
||
|
return {
|
||
|
installationEntry: installationEntry,
|
||
|
registrationPromise: registrationPromiseWithError
|
||
|
};
|
||
|
}
|
||
|
// Try registering. Change status to IN_PROGRESS.
|
||
|
var inProgressEntry = {
|
||
|
fid: installationEntry.fid,
|
||
|
registrationStatus: 1 /* RequestStatus.IN_PROGRESS */,
|
||
|
registrationTime: Date.now()
|
||
|
};
|
||
|
var registrationPromise = registerInstallation(installations, inProgressEntry);
|
||
|
return { installationEntry: inProgressEntry, registrationPromise: registrationPromise };
|
||
|
}
|
||
|
else if (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {
|
||
|
return {
|
||
|
installationEntry: installationEntry,
|
||
|
registrationPromise: waitUntilFidRegistration(installations)
|
||
|
};
|
||
|
}
|
||
|
else {
|
||
|
return { installationEntry: installationEntry };
|
||
|
}
|
||
|
}
|
||
|
/** This will be executed only once for each new Firebase Installation. */
|
||
|
function registerInstallation(installations, installationEntry) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var registeredInstallationEntry, e_1;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
_a.trys.push([0, 2, , 7]);
|
||
|
return [4 /*yield*/, createInstallationRequest(installations, installationEntry)];
|
||
|
case 1:
|
||
|
registeredInstallationEntry = _a.sent();
|
||
|
return [2 /*return*/, set(installations.appConfig, registeredInstallationEntry)];
|
||
|
case 2:
|
||
|
e_1 = _a.sent();
|
||
|
if (!(isServerError(e_1) && e_1.customData.serverCode === 409)) return [3 /*break*/, 4];
|
||
|
// Server returned a "FID can not be used" error.
|
||
|
// Generate a new ID next time.
|
||
|
return [4 /*yield*/, remove(installations.appConfig)];
|
||
|
case 3:
|
||
|
// Server returned a "FID can not be used" error.
|
||
|
// Generate a new ID next time.
|
||
|
_a.sent();
|
||
|
return [3 /*break*/, 6];
|
||
|
case 4:
|
||
|
// Registration failed. Set FID as not registered.
|
||
|
return [4 /*yield*/, set(installations.appConfig, {
|
||
|
fid: installationEntry.fid,
|
||
|
registrationStatus: 0 /* RequestStatus.NOT_STARTED */
|
||
|
})];
|
||
|
case 5:
|
||
|
// Registration failed. Set FID as not registered.
|
||
|
_a.sent();
|
||
|
_a.label = 6;
|
||
|
case 6: throw e_1;
|
||
|
case 7: return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
/** Call if FID registration is pending in another request. */
|
||
|
function waitUntilFidRegistration(installations) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var entry, _a, installationEntry, registrationPromise;
|
||
|
return tslib.__generator(this, function (_b) {
|
||
|
switch (_b.label) {
|
||
|
case 0: return [4 /*yield*/, updateInstallationRequest(installations.appConfig)];
|
||
|
case 1:
|
||
|
entry = _b.sent();
|
||
|
_b.label = 2;
|
||
|
case 2:
|
||
|
if (!(entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */)) return [3 /*break*/, 5];
|
||
|
// createInstallation request still in progress.
|
||
|
return [4 /*yield*/, sleep(100)];
|
||
|
case 3:
|
||
|
// createInstallation request still in progress.
|
||
|
_b.sent();
|
||
|
return [4 /*yield*/, updateInstallationRequest(installations.appConfig)];
|
||
|
case 4:
|
||
|
entry = _b.sent();
|
||
|
return [3 /*break*/, 2];
|
||
|
case 5:
|
||
|
if (!(entry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */)) return [3 /*break*/, 7];
|
||
|
return [4 /*yield*/, getInstallationEntry(installations)];
|
||
|
case 6:
|
||
|
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise;
|
||
|
if (registrationPromise) {
|
||
|
return [2 /*return*/, registrationPromise];
|
||
|
}
|
||
|
else {
|
||
|
// if there is no registrationPromise, entry is registered.
|
||
|
return [2 /*return*/, installationEntry];
|
||
|
}
|
||
|
case 7: return [2 /*return*/, entry];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
/**
|
||
|
* Called only if there is a CreateInstallation request in progress.
|
||
|
*
|
||
|
* Updates the InstallationEntry in the DB based on the status of the
|
||
|
* CreateInstallation request.
|
||
|
*
|
||
|
* Returns the updated InstallationEntry.
|
||
|
*/
|
||
|
function updateInstallationRequest(appConfig) {
|
||
|
return update(appConfig, function (oldEntry) {
|
||
|
if (!oldEntry) {
|
||
|
throw ERROR_FACTORY.create("installation-not-found" /* ErrorCode.INSTALLATION_NOT_FOUND */);
|
||
|
}
|
||
|
return clearTimedOutRequest(oldEntry);
|
||
|
});
|
||
|
}
|
||
|
function clearTimedOutRequest(entry) {
|
||
|
if (hasInstallationRequestTimedOut(entry)) {
|
||
|
return {
|
||
|
fid: entry.fid,
|
||
|
registrationStatus: 0 /* RequestStatus.NOT_STARTED */
|
||
|
};
|
||
|
}
|
||
|
return entry;
|
||
|
}
|
||
|
function hasInstallationRequestTimedOut(installationEntry) {
|
||
|
return (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */ &&
|
||
|
installationEntry.registrationTime + PENDING_TIMEOUT_MS < Date.now());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
function generateAuthTokenRequest(_a, installationEntry) {
|
||
|
var appConfig = _a.appConfig, heartbeatServiceProvider = _a.heartbeatServiceProvider;
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var endpoint, headers, heartbeatService, heartbeatsHeader, body, request, response, responseValue, completedAuthToken;
|
||
|
return tslib.__generator(this, function (_b) {
|
||
|
switch (_b.label) {
|
||
|
case 0:
|
||
|
endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);
|
||
|
headers = getHeadersWithAuth(appConfig, installationEntry);
|
||
|
heartbeatService = heartbeatServiceProvider.getImmediate({
|
||
|
optional: true
|
||
|
});
|
||
|
if (!heartbeatService) return [3 /*break*/, 2];
|
||
|
return [4 /*yield*/, heartbeatService.getHeartbeatsHeader()];
|
||
|
case 1:
|
||
|
heartbeatsHeader = _b.sent();
|
||
|
if (heartbeatsHeader) {
|
||
|
headers.append('x-firebase-client', heartbeatsHeader);
|
||
|
}
|
||
|
_b.label = 2;
|
||
|
case 2:
|
||
|
body = {
|
||
|
installation: {
|
||
|
sdkVersion: PACKAGE_VERSION,
|
||
|
appId: appConfig.appId
|
||
|
}
|
||
|
};
|
||
|
request = {
|
||
|
method: 'POST',
|
||
|
headers: headers,
|
||
|
body: JSON.stringify(body)
|
||
|
};
|
||
|
return [4 /*yield*/, retryIfServerError(function () { return fetch(endpoint, request); })];
|
||
|
case 3:
|
||
|
response = _b.sent();
|
||
|
if (!response.ok) return [3 /*break*/, 5];
|
||
|
return [4 /*yield*/, response.json()];
|
||
|
case 4:
|
||
|
responseValue = _b.sent();
|
||
|
completedAuthToken = extractAuthTokenInfoFromResponse(responseValue);
|
||
|
return [2 /*return*/, completedAuthToken];
|
||
|
case 5: return [4 /*yield*/, getErrorFromResponse('Generate Auth Token', response)];
|
||
|
case 6: throw _b.sent();
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
function getGenerateAuthTokenEndpoint(appConfig, _a) {
|
||
|
var fid = _a.fid;
|
||
|
return "".concat(getInstallationsEndpoint(appConfig), "/").concat(fid, "/authTokens:generate");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/**
|
||
|
* Returns a valid authentication token for the installation. Generates a new
|
||
|
* token if one doesn't exist, is expired or about to expire.
|
||
|
*
|
||
|
* Should only be called if the Firebase Installation is registered.
|
||
|
*/
|
||
|
function refreshAuthToken(installations, forceRefresh) {
|
||
|
if (forceRefresh === void 0) { forceRefresh = false; }
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var tokenPromise, entry, authToken, _a;
|
||
|
return tslib.__generator(this, function (_b) {
|
||
|
switch (_b.label) {
|
||
|
case 0: return [4 /*yield*/, update(installations.appConfig, function (oldEntry) {
|
||
|
if (!isEntryRegistered(oldEntry)) {
|
||
|
throw ERROR_FACTORY.create("not-registered" /* ErrorCode.NOT_REGISTERED */);
|
||
|
}
|
||
|
var oldAuthToken = oldEntry.authToken;
|
||
|
if (!forceRefresh && isAuthTokenValid(oldAuthToken)) {
|
||
|
// There is a valid token in the DB.
|
||
|
return oldEntry;
|
||
|
}
|
||
|
else if (oldAuthToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) {
|
||
|
// There already is a token request in progress.
|
||
|
tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh);
|
||
|
return oldEntry;
|
||
|
}
|
||
|
else {
|
||
|
// No token or token expired.
|
||
|
if (!navigator.onLine) {
|
||
|
throw ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */);
|
||
|
}
|
||
|
var inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry);
|
||
|
tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry);
|
||
|
return inProgressEntry;
|
||
|
}
|
||
|
})];
|
||
|
case 1:
|
||
|
entry = _b.sent();
|
||
|
if (!tokenPromise) return [3 /*break*/, 3];
|
||
|
return [4 /*yield*/, tokenPromise];
|
||
|
case 2:
|
||
|
_a = _b.sent();
|
||
|
return [3 /*break*/, 4];
|
||
|
case 3:
|
||
|
_a = entry.authToken;
|
||
|
_b.label = 4;
|
||
|
case 4:
|
||
|
authToken = _a;
|
||
|
return [2 /*return*/, authToken];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
/**
|
||
|
* Call only if FID is registered and Auth Token request is in progress.
|
||
|
*
|
||
|
* Waits until the current pending request finishes. If the request times out,
|
||
|
* tries once in this thread as well.
|
||
|
*/
|
||
|
function waitUntilAuthTokenRequest(installations, forceRefresh) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var entry, authToken;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0: return [4 /*yield*/, updateAuthTokenRequest(installations.appConfig)];
|
||
|
case 1:
|
||
|
entry = _a.sent();
|
||
|
_a.label = 2;
|
||
|
case 2:
|
||
|
if (!(entry.authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */)) return [3 /*break*/, 5];
|
||
|
// generateAuthToken still in progress.
|
||
|
return [4 /*yield*/, sleep(100)];
|
||
|
case 3:
|
||
|
// generateAuthToken still in progress.
|
||
|
_a.sent();
|
||
|
return [4 /*yield*/, updateAuthTokenRequest(installations.appConfig)];
|
||
|
case 4:
|
||
|
entry = _a.sent();
|
||
|
return [3 /*break*/, 2];
|
||
|
case 5:
|
||
|
authToken = entry.authToken;
|
||
|
if (authToken.requestStatus === 0 /* RequestStatus.NOT_STARTED */) {
|
||
|
// The request timed out or failed in a different call. Try again.
|
||
|
return [2 /*return*/, refreshAuthToken(installations, forceRefresh)];
|
||
|
}
|
||
|
else {
|
||
|
return [2 /*return*/, authToken];
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
/**
|
||
|
* Called only if there is a GenerateAuthToken request in progress.
|
||
|
*
|
||
|
* Updates the InstallationEntry in the DB based on the status of the
|
||
|
* GenerateAuthToken request.
|
||
|
*
|
||
|
* Returns the updated InstallationEntry.
|
||
|
*/
|
||
|
function updateAuthTokenRequest(appConfig) {
|
||
|
return update(appConfig, function (oldEntry) {
|
||
|
if (!isEntryRegistered(oldEntry)) {
|
||
|
throw ERROR_FACTORY.create("not-registered" /* ErrorCode.NOT_REGISTERED */);
|
||
|
}
|
||
|
var oldAuthToken = oldEntry.authToken;
|
||
|
if (hasAuthTokenRequestTimedOut(oldAuthToken)) {
|
||
|
return tslib.__assign(tslib.__assign({}, oldEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } });
|
||
|
}
|
||
|
return oldEntry;
|
||
|
});
|
||
|
}
|
||
|
function fetchAuthTokenFromServer(installations, installationEntry) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var authToken, updatedInstallationEntry, e_1, updatedInstallationEntry;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
_a.trys.push([0, 3, , 8]);
|
||
|
return [4 /*yield*/, generateAuthTokenRequest(installations, installationEntry)];
|
||
|
case 1:
|
||
|
authToken = _a.sent();
|
||
|
updatedInstallationEntry = tslib.__assign(tslib.__assign({}, installationEntry), { authToken: authToken });
|
||
|
return [4 /*yield*/, set(installations.appConfig, updatedInstallationEntry)];
|
||
|
case 2:
|
||
|
_a.sent();
|
||
|
return [2 /*return*/, authToken];
|
||
|
case 3:
|
||
|
e_1 = _a.sent();
|
||
|
if (!(isServerError(e_1) &&
|
||
|
(e_1.customData.serverCode === 401 || e_1.customData.serverCode === 404))) return [3 /*break*/, 5];
|
||
|
// Server returned a "FID not found" or a "Invalid authentication" error.
|
||
|
// Generate a new ID next time.
|
||
|
return [4 /*yield*/, remove(installations.appConfig)];
|
||
|
case 4:
|
||
|
// Server returned a "FID not found" or a "Invalid authentication" error.
|
||
|
// Generate a new ID next time.
|
||
|
_a.sent();
|
||
|
return [3 /*break*/, 7];
|
||
|
case 5:
|
||
|
updatedInstallationEntry = tslib.__assign(tslib.__assign({}, installationEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } });
|
||
|
return [4 /*yield*/, set(installations.appConfig, updatedInstallationEntry)];
|
||
|
case 6:
|
||
|
_a.sent();
|
||
|
_a.label = 7;
|
||
|
case 7: throw e_1;
|
||
|
case 8: return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
function isEntryRegistered(installationEntry) {
|
||
|
return (installationEntry !== undefined &&
|
||
|
installationEntry.registrationStatus === 2 /* RequestStatus.COMPLETED */);
|
||
|
}
|
||
|
function isAuthTokenValid(authToken) {
|
||
|
return (authToken.requestStatus === 2 /* RequestStatus.COMPLETED */ &&
|
||
|
!isAuthTokenExpired(authToken));
|
||
|
}
|
||
|
function isAuthTokenExpired(authToken) {
|
||
|
var now = Date.now();
|
||
|
return (now < authToken.creationTime ||
|
||
|
authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER);
|
||
|
}
|
||
|
/** Returns an updated InstallationEntry with an InProgressAuthToken. */
|
||
|
function makeAuthTokenRequestInProgressEntry(oldEntry) {
|
||
|
var inProgressAuthToken = {
|
||
|
requestStatus: 1 /* RequestStatus.IN_PROGRESS */,
|
||
|
requestTime: Date.now()
|
||
|
};
|
||
|
return tslib.__assign(tslib.__assign({}, oldEntry), { authToken: inProgressAuthToken });
|
||
|
}
|
||
|
function hasAuthTokenRequestTimedOut(authToken) {
|
||
|
return (authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */ &&
|
||
|
authToken.requestTime + PENDING_TIMEOUT_MS < Date.now());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/**
|
||
|
* Creates a Firebase Installation if there isn't one for the app and
|
||
|
* returns the Installation ID.
|
||
|
* @param installations - The `Installations` instance.
|
||
|
*
|
||
|
* @public
|
||
|
*/
|
||
|
function getId(installations) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var installationsImpl, _a, installationEntry, registrationPromise;
|
||
|
return tslib.__generator(this, function (_b) {
|
||
|
switch (_b.label) {
|
||
|
case 0:
|
||
|
installationsImpl = installations;
|
||
|
return [4 /*yield*/, getInstallationEntry(installationsImpl)];
|
||
|
case 1:
|
||
|
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise;
|
||
|
if (registrationPromise) {
|
||
|
registrationPromise.catch(console.error);
|
||
|
}
|
||
|
else {
|
||
|
// If the installation is already registered, update the authentication
|
||
|
// token if needed.
|
||
|
refreshAuthToken(installationsImpl).catch(console.error);
|
||
|
}
|
||
|
return [2 /*return*/, installationEntry.fid];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/**
|
||
|
* Returns a Firebase Installations auth token, identifying the current
|
||
|
* Firebase Installation.
|
||
|
* @param installations - The `Installations` instance.
|
||
|
* @param forceRefresh - Force refresh regardless of token expiration.
|
||
|
*
|
||
|
* @public
|
||
|
*/
|
||
|
function getToken(installations, forceRefresh) {
|
||
|
if (forceRefresh === void 0) { forceRefresh = false; }
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var installationsImpl, authToken;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
installationsImpl = installations;
|
||
|
return [4 /*yield*/, completeInstallationRegistration(installationsImpl)];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
return [4 /*yield*/, refreshAuthToken(installationsImpl, forceRefresh)];
|
||
|
case 2:
|
||
|
authToken = _a.sent();
|
||
|
return [2 /*return*/, authToken.token];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
function completeInstallationRegistration(installations) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var registrationPromise;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0: return [4 /*yield*/, getInstallationEntry(installations)];
|
||
|
case 1:
|
||
|
registrationPromise = (_a.sent()).registrationPromise;
|
||
|
if (!registrationPromise) return [3 /*break*/, 3];
|
||
|
// A createInstallation request is in progress. Wait until it finishes.
|
||
|
return [4 /*yield*/, registrationPromise];
|
||
|
case 2:
|
||
|
// A createInstallation request is in progress. Wait until it finishes.
|
||
|
_a.sent();
|
||
|
_a.label = 3;
|
||
|
case 3: return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
function deleteInstallationRequest(appConfig, installationEntry) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var endpoint, headers, request, response;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
endpoint = getDeleteEndpoint(appConfig, installationEntry);
|
||
|
headers = getHeadersWithAuth(appConfig, installationEntry);
|
||
|
request = {
|
||
|
method: 'DELETE',
|
||
|
headers: headers
|
||
|
};
|
||
|
return [4 /*yield*/, retryIfServerError(function () { return fetch(endpoint, request); })];
|
||
|
case 1:
|
||
|
response = _a.sent();
|
||
|
if (!!response.ok) return [3 /*break*/, 3];
|
||
|
return [4 /*yield*/, getErrorFromResponse('Delete Installation', response)];
|
||
|
case 2: throw _a.sent();
|
||
|
case 3: return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
function getDeleteEndpoint(appConfig, _a) {
|
||
|
var fid = _a.fid;
|
||
|
return "".concat(getInstallationsEndpoint(appConfig), "/").concat(fid);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/**
|
||
|
* Deletes the Firebase Installation and all associated data.
|
||
|
* @param installations - The `Installations` instance.
|
||
|
*
|
||
|
* @public
|
||
|
*/
|
||
|
function deleteInstallations(installations) {
|
||
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
||
|
var appConfig, entry;
|
||
|
return tslib.__generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
appConfig = installations.appConfig;
|
||
|
return [4 /*yield*/, update(appConfig, function (oldEntry) {
|
||
|
if (oldEntry && oldEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {
|
||
|
// Delete the unregistered entry without sending a deleteInstallation request.
|
||
|
return undefined;
|
||
|
}
|
||
|
return oldEntry;
|
||
|
})];
|
||
|
case 1:
|
||
|
entry = _a.sent();
|
||
|
if (!entry) return [3 /*break*/, 6];
|
||
|
if (!(entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */)) return [3 /*break*/, 2];
|
||
|
// Can't delete while trying to register.
|
||
|
throw ERROR_FACTORY.create("delete-pending-registration" /* ErrorCode.DELETE_PENDING_REGISTRATION */);
|
||
|
case 2:
|
||
|
if (!(entry.registrationStatus === 2 /* RequestStatus.COMPLETED */)) return [3 /*break*/, 6];
|
||
|
if (!!navigator.onLine) return [3 /*break*/, 3];
|
||
|
throw ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */);
|
||
|
case 3: return [4 /*yield*/, deleteInstallationRequest(appConfig, entry)];
|
||
|
case 4:
|
||
|
_a.sent();
|
||
|
return [4 /*yield*/, remove(appConfig)];
|
||
|
case 5:
|
||
|
_a.sent();
|
||
|
_a.label = 6;
|
||
|
case 6: return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/**
|
||
|
* Sets a new callback that will get called when Installation ID changes.
|
||
|
* Returns an unsubscribe function that will remove the callback when called.
|
||
|
* @param installations - The `Installations` instance.
|
||
|
* @param callback - The callback function that is invoked when FID changes.
|
||
|
* @returns A function that can be called to unsubscribe.
|
||
|
*
|
||
|
* @public
|
||
|
*/
|
||
|
function onIdChange(installations, callback) {
|
||
|
var appConfig = installations.appConfig;
|
||
|
addCallback(appConfig, callback);
|
||
|
return function () {
|
||
|
removeCallback(appConfig, callback);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2020 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
/**
|
||
|
* Returns an instance of {@link Installations} associated with the given
|
||
|
* {@link @firebase/app#FirebaseApp} instance.
|
||
|
* @param app - The {@link @firebase/app#FirebaseApp} instance.
|
||
|
*
|
||
|
* @public
|
||
|
*/
|
||
|
function getInstallations(app$1) {
|
||
|
if (app$1 === void 0) { app$1 = app.getApp(); }
|
||
|
var installationsImpl = app._getProvider(app$1, 'installations').getImmediate();
|
||
|
return installationsImpl;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2019 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
function extractAppConfig(app) {
|
||
|
var e_1, _a;
|
||
|
if (!app || !app.options) {
|
||
|
throw getMissingValueError('App Configuration');
|
||
|
}
|
||
|
if (!app.name) {
|
||
|
throw getMissingValueError('App Name');
|
||
|
}
|
||
|
// Required app config keys
|
||
|
var configKeys = [
|
||
|
'projectId',
|
||
|
'apiKey',
|
||
|
'appId'
|
||
|
];
|
||
|
try {
|
||
|
for (var configKeys_1 = tslib.__values(configKeys), configKeys_1_1 = configKeys_1.next(); !configKeys_1_1.done; configKeys_1_1 = configKeys_1.next()) {
|
||
|
var keyName = configKeys_1_1.value;
|
||
|
if (!app.options[keyName]) {
|
||
|
throw getMissingValueError(keyName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||
|
finally {
|
||
|
try {
|
||
|
if (configKeys_1_1 && !configKeys_1_1.done && (_a = configKeys_1.return)) _a.call(configKeys_1);
|
||
|
}
|
||
|
finally { if (e_1) throw e_1.error; }
|
||
|
}
|
||
|
return {
|
||
|
appName: app.name,
|
||
|
projectId: app.options.projectId,
|
||
|
apiKey: app.options.apiKey,
|
||
|
appId: app.options.appId
|
||
|
};
|
||
|
}
|
||
|
function getMissingValueError(valueName) {
|
||
|
return ERROR_FACTORY.create("missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */, {
|
||
|
valueName: valueName
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @license
|
||
|
* Copyright 2020 Google LLC
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
var INSTALLATIONS_NAME = 'installations';
|
||
|
var INSTALLATIONS_NAME_INTERNAL = 'installations-internal';
|
||
|
var publicFactory = function (container) {
|
||
|
var app$1 = container.getProvider('app').getImmediate();
|
||
|
// Throws if app isn't configured properly.
|
||
|
var appConfig = extractAppConfig(app$1);
|
||
|
var heartbeatServiceProvider = app._getProvider(app$1, 'heartbeat');
|
||
|
var installationsImpl = {
|
||
|
app: app$1,
|
||
|
appConfig: appConfig,
|
||
|
heartbeatServiceProvider: heartbeatServiceProvider,
|
||
|
_delete: function () { return Promise.resolve(); }
|
||
|
};
|
||
|
return installationsImpl;
|
||
|
};
|
||
|
var internalFactory = function (container) {
|
||
|
var app$1 = container.getProvider('app').getImmediate();
|
||
|
// Internal FIS instance relies on public FIS instance.
|
||
|
var installations = app._getProvider(app$1, INSTALLATIONS_NAME).getImmediate();
|
||
|
var installationsInternal = {
|
||
|
getId: function () { return getId(installations); },
|
||
|
getToken: function (forceRefresh) { return getToken(installations, forceRefresh); }
|
||
|
};
|
||
|
return installationsInternal;
|
||
|
};
|
||
|
function registerInstallations() {
|
||
|
app._registerComponent(new component.Component(INSTALLATIONS_NAME, publicFactory, "PUBLIC" /* ComponentType.PUBLIC */));
|
||
|
app._registerComponent(new component.Component(INSTALLATIONS_NAME_INTERNAL, internalFactory, "PRIVATE" /* ComponentType.PRIVATE */));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The Firebase Installations Web SDK.
|
||
|
* This SDK does not work in a Node.js environment.
|
||
|
*
|
||
|
* @packageDocumentation
|
||
|
*/
|
||
|
registerInstallations();
|
||
|
app.registerVersion(name, version);
|
||
|
// BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
|
||
|
app.registerVersion(name, version, 'cjs5');
|
||
|
|
||
|
exports.deleteInstallations = deleteInstallations;
|
||
|
exports.getId = getId;
|
||
|
exports.getInstallations = getInstallations;
|
||
|
exports.getToken = getToken;
|
||
|
exports.onIdChange = onIdChange;
|
||
|
//# sourceMappingURL=index.cjs.js.map
|