GT2/Ejectable/node_modules/expo-web-browser/build/WebBrowser.js

220 lines
7.9 KiB
JavaScript
Raw Normal View History

2021-08-16 00:14:59 +00:00
import { UnavailabilityError } from '@unimodules/core';
import { AppState, Linking, Platform } from 'react-native';
import ExponentWebBrowser from './ExpoWebBrowser';
import { WebBrowserResultType, } from './WebBrowser.types';
export { WebBrowserResultType, };
const emptyCustomTabsPackages = {
defaultBrowserPackage: undefined,
preferredBrowserPackage: undefined,
browserPackages: [],
servicePackages: [],
};
export async function getCustomTabsSupportingBrowsersAsync() {
if (!ExponentWebBrowser.getCustomTabsSupportingBrowsersAsync) {
throw new UnavailabilityError('WebBrowser', 'getCustomTabsSupportingBrowsersAsync');
}
if (Platform.OS !== 'android') {
return emptyCustomTabsPackages;
}
else {
return await ExponentWebBrowser.getCustomTabsSupportingBrowsersAsync();
}
}
export async function warmUpAsync(browserPackage) {
if (!ExponentWebBrowser.warmUpAsync) {
throw new UnavailabilityError('WebBrowser', 'warmUpAsync');
}
if (Platform.OS !== 'android') {
return {};
}
else {
return await ExponentWebBrowser.warmUpAsync(browserPackage);
}
}
export async function mayInitWithUrlAsync(url, browserPackage) {
if (!ExponentWebBrowser.mayInitWithUrlAsync) {
throw new UnavailabilityError('WebBrowser', 'mayInitWithUrlAsync');
}
if (Platform.OS !== 'android') {
return {};
}
else {
return await ExponentWebBrowser.mayInitWithUrlAsync(url, browserPackage);
}
}
export async function coolDownAsync(browserPackage) {
if (!ExponentWebBrowser.coolDownAsync) {
throw new UnavailabilityError('WebBrowser', 'coolDownAsync');
}
if (Platform.OS !== 'android') {
return {};
}
else {
return await ExponentWebBrowser.coolDownAsync(browserPackage);
}
}
let browserLocked = false;
export async function openBrowserAsync(url, browserParams = {}) {
if (!ExponentWebBrowser.openBrowserAsync) {
throw new UnavailabilityError('WebBrowser', 'openBrowserAsync');
}
if (browserLocked) {
// Prevent multiple sessions from running at the same time, WebBrowser doesn't
// support it this makes the behavior predictable.
if (__DEV__) {
console.warn('Attempted to call WebBrowser.openBrowserAsync multiple times while already active. Only one WebBrowser controller can be active at any given time.');
}
return { type: WebBrowserResultType.LOCKED };
}
browserLocked = true;
let result;
try {
result = await ExponentWebBrowser.openBrowserAsync(url, browserParams);
}
finally {
// WebBrowser session complete, unset lock
browserLocked = false;
}
return result;
}
export function dismissBrowser() {
if (!ExponentWebBrowser.dismissBrowser) {
throw new UnavailabilityError('WebBrowser', 'dismissBrowser');
}
ExponentWebBrowser.dismissBrowser();
}
export async function openAuthSessionAsync(url, redirectUrl, browserParams = {}) {
if (_authSessionIsNativelySupported()) {
if (!ExponentWebBrowser.openAuthSessionAsync) {
throw new UnavailabilityError('WebBrowser', 'openAuthSessionAsync');
}
if (Platform.OS === 'web') {
return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl, browserParams);
}
return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl);
}
else {
return _openAuthSessionPolyfillAsync(url, redirectUrl, browserParams);
}
}
export function dismissAuthSession() {
if (_authSessionIsNativelySupported()) {
if (!ExponentWebBrowser.dismissAuthSession) {
throw new UnavailabilityError('WebBrowser', 'dismissAuthSession');
}
ExponentWebBrowser.dismissAuthSession();
}
else {
if (!ExponentWebBrowser.dismissBrowser) {
throw new UnavailabilityError('WebBrowser', 'dismissAuthSession');
}
ExponentWebBrowser.dismissBrowser();
}
}
/**
* Attempts to complete an auth session in the browser.
*
* @param options
*/
export function maybeCompleteAuthSession(options = {}) {
if (ExponentWebBrowser.maybeCompleteAuthSession) {
return ExponentWebBrowser.maybeCompleteAuthSession(options);
}
return { type: 'failed', message: 'Not supported on this platform' };
}
/* iOS <= 10 and Android polyfill for SFAuthenticationSession flow */
function _authSessionIsNativelySupported() {
if (Platform.OS === 'android') {
return false;
}
else if (Platform.OS === 'web') {
return true;
}
const versionNumber = parseInt(String(Platform.Version), 10);
return versionNumber >= 11;
}
let _redirectHandler = null;
/*
* openBrowserAsync on Android doesn't wait until closed, so we need to polyfill
* it with AppState
*/
// Store the `resolve` function from a Promise to fire when the AppState
// returns to active
let _onWebBrowserCloseAndroid = null;
// If the initial AppState.currentState is null, we assume that the first call to
// AppState#change event is not actually triggered by a real change,
// is triggered instead by the bridge capturing the current state
// (https://reactnative.dev/docs/appstate#basic-usage)
let _isAppStateAvailable = AppState.currentState !== null;
function _onAppStateChangeAndroid(state) {
if (!_isAppStateAvailable) {
_isAppStateAvailable = true;
return;
}
if (state === 'active' && _onWebBrowserCloseAndroid) {
_onWebBrowserCloseAndroid();
}
}
async function _openBrowserAndWaitAndroidAsync(startUrl, browserParams = {}) {
const appStateChangedToActive = new Promise(resolve => {
_onWebBrowserCloseAndroid = resolve;
AppState.addEventListener('change', _onAppStateChangeAndroid);
});
let result = { type: WebBrowserResultType.CANCEL };
const { type } = await openBrowserAsync(startUrl, browserParams);
if (type === 'opened') {
await appStateChangedToActive;
result = { type: WebBrowserResultType.DISMISS };
}
AppState.removeEventListener('change', _onAppStateChangeAndroid);
_onWebBrowserCloseAndroid = null;
return result;
}
async function _openAuthSessionPolyfillAsync(startUrl, returnUrl, browserParams = {}) {
if (_redirectHandler) {
throw new Error(`The WebBrowser's auth session is in an invalid state with a redirect handler set when it should not be`);
}
if (_onWebBrowserCloseAndroid) {
throw new Error(`WebBrowser is already open, only one can be open at a time`);
}
try {
if (Platform.OS === 'android') {
return await Promise.race([
_openBrowserAndWaitAndroidAsync(startUrl, browserParams),
_waitForRedirectAsync(returnUrl),
]);
}
else {
return await Promise.race([
openBrowserAsync(startUrl, browserParams),
_waitForRedirectAsync(returnUrl),
]);
}
}
finally {
// We can't dismiss the browser on Android, only call this when it's available.
// Users on Android need to manually press the 'x' button in Chrome Custom Tabs, sadly.
if (ExponentWebBrowser.dismissBrowser) {
ExponentWebBrowser.dismissBrowser();
}
_stopWaitingForRedirect();
}
}
function _stopWaitingForRedirect() {
if (!_redirectHandler) {
throw new Error(`The WebBrowser auth session is in an invalid state with no redirect handler when one should be set`);
}
Linking.removeEventListener('url', _redirectHandler);
_redirectHandler = null;
}
function _waitForRedirectAsync(returnUrl) {
return new Promise(resolve => {
_redirectHandler = (event) => {
if (event.url.startsWith(returnUrl)) {
resolve({ url: event.url, type: 'success' });
}
};
Linking.addEventListener('url', _redirectHandler);
});
}
//# sourceMappingURL=WebBrowser.js.map