expo-web-browser 11.0.0 β 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +1 -1
- package/android/build.gradle +4 -4
- package/android/src/main/java/expo/modules/webbrowser/WebBrowserModule.kt +7 -13
- package/android/src/main/java/expo/modules/webbrowser/WebBrowserOptions.kt +2 -2
- package/build/ExpoWebBrowser.web.d.ts +1 -1
- package/build/ExpoWebBrowser.web.d.ts.map +1 -1
- package/build/WebBrowser.d.ts +7 -4
- package/build/WebBrowser.d.ts.map +1 -1
- package/build/WebBrowser.js +18 -7
- package/build/WebBrowser.js.map +1 -1
- package/build/WebBrowser.types.d.ts +17 -17
- package/build/WebBrowser.types.d.ts.map +1 -1
- package/build/WebBrowser.types.js.map +1 -1
- package/ios/ExpoWebBrowser.podspec +1 -1
- package/package.json +5 -4
- package/src/WebBrowser.ts +26 -7
- package/src/WebBrowser.types.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,30 @@
|
|
|
10
10
|
|
|
11
11
|
### π‘ Others
|
|
12
12
|
|
|
13
|
+
## 12.1.0 β 2023-02-03
|
|
14
|
+
|
|
15
|
+
### π Bug fixes
|
|
16
|
+
|
|
17
|
+
- Add missing peer dependency on `url` for web. ([#20708](https://github.com/expo/expo/pull/20708) by [@EvanBacon](https://github.com/EvanBacon))
|
|
18
|
+
|
|
19
|
+
### π‘ Others
|
|
20
|
+
|
|
21
|
+
- On Android bump `compileSdkVersion` and `targetSdkVersion` to `33`. ([#20721](https://github.com/expo/expo/pull/20721) by [@lukmccall](https://github.com/lukmccall))
|
|
22
|
+
|
|
23
|
+
## 12.0.0 β 2022-10-25
|
|
24
|
+
|
|
25
|
+
### π Breaking changes
|
|
26
|
+
|
|
27
|
+
- Bumped iOS deployment target to 13.0 and deprecated support for iOS 12. ([#18873](https://github.com/expo/expo/pull/18873) by [@tsapeta](https://github.com/tsapeta))
|
|
28
|
+
|
|
29
|
+
### π New features
|
|
30
|
+
|
|
31
|
+
- Support CSS colors in `controlsColor`, `toolbarColor` and `secondaryToolbarColor` options. ([#18586](https://github.com/expo/expo/pull/18586) by [@janicduplessis](https://github.com/janicduplessis))
|
|
32
|
+
|
|
33
|
+
### π‘ Others
|
|
34
|
+
|
|
35
|
+
- Update docs to remove mentions of `expo start:web`. ([#18419](https://github.com/expo/expo/pull/18419) by [@EvanBacon](https://github.com/EvanBacon))
|
|
36
|
+
|
|
13
37
|
## 11.0.0 β 2022-07-07
|
|
14
38
|
|
|
15
39
|
### π New features
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Provides access to the system's web browser and supports handling redirects. On
|
|
|
4
4
|
|
|
5
5
|
# API documentation
|
|
6
6
|
|
|
7
|
-
- [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/webbrowser.
|
|
7
|
+
- [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/webbrowser.mdx)
|
|
8
8
|
- [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/webbrowser/)
|
|
9
9
|
|
|
10
10
|
# Installation in managed Expo projects
|
package/android/build.gradle
CHANGED
|
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
|
|
|
3
3
|
apply plugin: 'maven-publish'
|
|
4
4
|
|
|
5
5
|
group = 'host.exp.exponent'
|
|
6
|
-
version = '
|
|
6
|
+
version = '12.1.0'
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
buildscript {
|
|
@@ -60,7 +60,7 @@ afterEvaluate {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
android {
|
|
63
|
-
compileSdkVersion safeExtGet("compileSdkVersion",
|
|
63
|
+
compileSdkVersion safeExtGet("compileSdkVersion", 33)
|
|
64
64
|
|
|
65
65
|
compileOptions {
|
|
66
66
|
sourceCompatibility JavaVersion.VERSION_11
|
|
@@ -73,9 +73,9 @@ android {
|
|
|
73
73
|
|
|
74
74
|
defaultConfig {
|
|
75
75
|
minSdkVersion safeExtGet("minSdkVersion", 21)
|
|
76
|
-
targetSdkVersion safeExtGet("targetSdkVersion",
|
|
76
|
+
targetSdkVersion safeExtGet("targetSdkVersion", 33)
|
|
77
77
|
versionCode 18
|
|
78
|
-
versionName '
|
|
78
|
+
versionName '12.1.0'
|
|
79
79
|
}
|
|
80
80
|
lintOptions {
|
|
81
81
|
abortOnError false
|
|
@@ -2,7 +2,6 @@ package expo.modules.webbrowser
|
|
|
2
2
|
|
|
3
3
|
import expo.modules.core.errors.CurrentActivityNotFoundException
|
|
4
4
|
import android.content.Intent
|
|
5
|
-
import android.graphics.Color
|
|
6
5
|
import android.net.Uri
|
|
7
6
|
import android.os.Bundle
|
|
8
7
|
import android.text.TextUtils
|
|
@@ -11,7 +10,6 @@ import androidx.core.os.bundleOf
|
|
|
11
10
|
import expo.modules.core.utilities.ifNull
|
|
12
11
|
import expo.modules.kotlin.modules.Module
|
|
13
12
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
14
|
-
import java.lang.IllegalArgumentException
|
|
15
13
|
|
|
16
14
|
private const val SERVICE_PACKAGE_KEY = "servicePackage"
|
|
17
15
|
private const val BROWSER_PACKAGES_KEY = "browserPackages"
|
|
@@ -108,19 +106,15 @@ class WebBrowserModule : Module() {
|
|
|
108
106
|
|
|
109
107
|
private fun createCustomTabsIntent(options: OpenBrowserOptions): Intent {
|
|
110
108
|
val builder = CustomTabsIntent.Builder()
|
|
109
|
+
|
|
111
110
|
val color = options.toolbarColor
|
|
112
|
-
|
|
111
|
+
if (color != null) {
|
|
112
|
+
builder.setToolbarColor(color)
|
|
113
|
+
}
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
builder.setToolbarColor(intColor)
|
|
118
|
-
}
|
|
119
|
-
if (!TextUtils.isEmpty(secondaryColor)) {
|
|
120
|
-
val intSecondaryColor = Color.parseColor(secondaryColor)
|
|
121
|
-
builder.setSecondaryToolbarColor(intSecondaryColor)
|
|
122
|
-
}
|
|
123
|
-
} catch (ignored: IllegalArgumentException) {
|
|
115
|
+
val secondaryColor = options.secondaryToolbarColor
|
|
116
|
+
if (secondaryColor != null) {
|
|
117
|
+
builder.setSecondaryToolbarColor(secondaryColor)
|
|
124
118
|
}
|
|
125
119
|
|
|
126
120
|
builder.setShowTitle(options.showTitle)
|
|
@@ -4,8 +4,8 @@ import expo.modules.kotlin.records.Field
|
|
|
4
4
|
import expo.modules.kotlin.records.Record
|
|
5
5
|
|
|
6
6
|
internal data class OpenBrowserOptions(
|
|
7
|
-
@Field var toolbarColor:
|
|
8
|
-
@Field var secondaryToolbarColor:
|
|
7
|
+
@Field var toolbarColor: Int? = null,
|
|
8
|
+
@Field var secondaryToolbarColor: Int? = null,
|
|
9
9
|
@Field var browserPackage: String? = null,
|
|
10
10
|
@Field var showTitle: Boolean = false,
|
|
11
11
|
@Field var enableDefaultShareMenuItem: Boolean = false,
|
|
@@ -9,7 +9,7 @@ declare const _default: {
|
|
|
9
9
|
type: 'success' | 'failed';
|
|
10
10
|
message: string;
|
|
11
11
|
};
|
|
12
|
-
openAuthSessionAsync(url: string, redirectUrl?: string
|
|
12
|
+
openAuthSessionAsync(url: string, redirectUrl?: string, openOptions?: WebBrowserOpenOptions): Promise<WebBrowserAuthSessionResult>;
|
|
13
13
|
};
|
|
14
14
|
export default _default;
|
|
15
15
|
export declare function featureObjectToString(features: Record<string, any>): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoWebBrowser.web.d.ts","sourceRoot":"","sources":["../src/ExpoWebBrowser.web.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,EACrB,gBAAgB,EAGjB,MAAM,oBAAoB,CAAC;;;0BAyCnB,MAAM,kBACI,qBAAqB,GACnC,QAAQ,gBAAgB,CAAC;;;;QAWsD;QAChF,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC;KACjB;8BA8CM,MAAM,
|
|
1
|
+
{"version":3,"file":"ExpoWebBrowser.web.d.ts","sourceRoot":"","sources":["../src/ExpoWebBrowser.web.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,EACrB,gBAAgB,EAGjB,MAAM,oBAAoB,CAAC;;;0BAyCnB,MAAM,kBACI,qBAAqB,GACnC,QAAQ,gBAAgB,CAAC;;;;QAWsD;QAChF,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC;KACjB;8BA8CM,MAAM,gBACG,MAAM,gBACN,qBAAqB,GAClC,QAAQ,2BAA2B,CAAC;;AAtEzC,wBAyJE;AAqIF,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAY3E"}
|
package/build/WebBrowser.d.ts
CHANGED
|
@@ -70,9 +70,12 @@ export declare function openBrowserAsync(url: string, browserParams?: WebBrowser
|
|
|
70
70
|
export declare function dismissBrowser(): void;
|
|
71
71
|
/**
|
|
72
72
|
* # On iOS:
|
|
73
|
-
* Opens the url with Safari in a modal using `
|
|
74
|
-
*
|
|
75
|
-
* to
|
|
73
|
+
* Opens the url with Safari in a modal using `ASWebAuthenticationSession`. The user will be asked
|
|
74
|
+
* whether to allow the app to authenticate using the given url.
|
|
75
|
+
* To handle redirection back to the mobile application, the redirect URI set in the authentication server
|
|
76
|
+
* has to use the protocol provided as the scheme in **app.json** [`expo.scheme`](./../config/app/#scheme)
|
|
77
|
+
* e.g. `demo://` not `https://` protocol.
|
|
78
|
+
* Using `Linking.addEventListener` is not needed and can have side effects.
|
|
76
79
|
*
|
|
77
80
|
* # On Android:
|
|
78
81
|
* This will be done using a "custom Chrome tabs" browser, [AppState](../react-native/appstate/),
|
|
@@ -87,7 +90,7 @@ export declare function dismissBrowser(): void;
|
|
|
87
90
|
*
|
|
88
91
|
* How this works on web:
|
|
89
92
|
* - A crypto state will be created for verifying the redirect.
|
|
90
|
-
* - This means you need to run with `expo start
|
|
93
|
+
* - This means you need to run with `npx expo start --https`
|
|
91
94
|
* - The state will be added to the window's `localstorage`. This ensures that auth cannot complete
|
|
92
95
|
* unless it's done from a page running with the same origin as it was started.
|
|
93
96
|
* Ex: if `openAuthSessionAsync` is invoked on `https://localhost:19006`, then `maybeCompleteAuthSession`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebBrowser.d.ts","sourceRoot":"","sources":["../src/WebBrowser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WebBrowser.d.ts","sourceRoot":"","sources":["../src/WebBrowser.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,2BAA2B,EAC3B,oCAAoC,EACpC,mCAAmC,EACnC,wBAAwB,EACxB,2BAA2B,EAC3B,8BAA8B,EAC9B,qBAAqB,EACrB,wBAAwB,EACxB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,wBAAwB,EACxB,2BAA2B,EAC3B,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,2BAA2B,EAC3B,oCAAoC,EACpC,mCAAmC,EACnC,wBAAwB,EACxB,2BAA2B,EAC3B,8BAA8B,EAC9B,qBAAqB,EACrB,wBAAwB,EACxB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,wBAAwB,EACxB,2BAA2B,EAC3B,sBAAsB,GACvB,CAAC;AAUF;;;;;;;;GAQG;AACH,wBAAsB,oCAAoC,IAAI,OAAO,CAAC,2BAA2B,CAAC,CASjG;AAGD;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAS1F;AAGD;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,8BAA8B,CAAC,CASzC;AAGD;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAS9F;AAKD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,aAAa,GAAE,qBAA0B,GACxC,OAAO,CAAC,gBAAgB,CAAC,CA2B3B;AAGD;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAKrC;AAGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,EACX,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,EAC3B,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,2BAA2B,CAAC,CAYtC;AAGD,wBAAgB,kBAAkB,IAAI,IAAI,CAYzC;AAGD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,GAAE,oCAAyC,GACjD,mCAAmC,CAKrC"}
|
package/build/WebBrowser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UnavailabilityError } from 'expo-modules-core';
|
|
2
|
-
import { AppState, Linking, Platform } from 'react-native';
|
|
2
|
+
import { AppState, Linking, Platform, processColor, } from 'react-native';
|
|
3
3
|
import ExponentWebBrowser from './ExpoWebBrowser';
|
|
4
4
|
import { WebBrowserResultType, WebBrowserPresentationStyle, } from './WebBrowser.types';
|
|
5
5
|
export { WebBrowserResultType, WebBrowserPresentationStyle, };
|
|
@@ -130,7 +130,7 @@ export async function openBrowserAsync(url, browserParams = {}) {
|
|
|
130
130
|
browserLocked = true;
|
|
131
131
|
let result;
|
|
132
132
|
try {
|
|
133
|
-
result = await ExponentWebBrowser.openBrowserAsync(url, browserParams);
|
|
133
|
+
result = await ExponentWebBrowser.openBrowserAsync(url, _processOptions(browserParams));
|
|
134
134
|
}
|
|
135
135
|
finally {
|
|
136
136
|
// WebBrowser session complete, unset lock
|
|
@@ -154,9 +154,12 @@ export function dismissBrowser() {
|
|
|
154
154
|
// @needsAudit
|
|
155
155
|
/**
|
|
156
156
|
* # On iOS:
|
|
157
|
-
* Opens the url with Safari in a modal using `
|
|
158
|
-
*
|
|
159
|
-
* to
|
|
157
|
+
* Opens the url with Safari in a modal using `ASWebAuthenticationSession`. The user will be asked
|
|
158
|
+
* whether to allow the app to authenticate using the given url.
|
|
159
|
+
* To handle redirection back to the mobile application, the redirect URI set in the authentication server
|
|
160
|
+
* has to use the protocol provided as the scheme in **app.json** [`expo.scheme`](./../config/app/#scheme)
|
|
161
|
+
* e.g. `demo://` not `https://` protocol.
|
|
162
|
+
* Using `Linking.addEventListener` is not needed and can have side effects.
|
|
160
163
|
*
|
|
161
164
|
* # On Android:
|
|
162
165
|
* This will be done using a "custom Chrome tabs" browser, [AppState](../react-native/appstate/),
|
|
@@ -171,7 +174,7 @@ export function dismissBrowser() {
|
|
|
171
174
|
*
|
|
172
175
|
* How this works on web:
|
|
173
176
|
* - A crypto state will be created for verifying the redirect.
|
|
174
|
-
* - This means you need to run with `expo start
|
|
177
|
+
* - This means you need to run with `npx expo start --https`
|
|
175
178
|
* - The state will be added to the window's `localstorage`. This ensures that auth cannot complete
|
|
176
179
|
* unless it's done from a page running with the same origin as it was started.
|
|
177
180
|
* Ex: if `openAuthSessionAsync` is invoked on `https://localhost:19006`, then `maybeCompleteAuthSession`
|
|
@@ -204,7 +207,7 @@ export async function openAuthSessionAsync(url, redirectUrl, options = {}) {
|
|
|
204
207
|
throw new UnavailabilityError('WebBrowser', 'openAuthSessionAsync');
|
|
205
208
|
}
|
|
206
209
|
if (['ios', 'web'].includes(Platform.OS)) {
|
|
207
|
-
return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl, options);
|
|
210
|
+
return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl, _processOptions(options));
|
|
208
211
|
}
|
|
209
212
|
return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl);
|
|
210
213
|
}
|
|
@@ -262,6 +265,14 @@ export function maybeCompleteAuthSession(options = {}) {
|
|
|
262
265
|
}
|
|
263
266
|
return { type: 'failed', message: 'Not supported on this platform' };
|
|
264
267
|
}
|
|
268
|
+
function _processOptions(options) {
|
|
269
|
+
return {
|
|
270
|
+
...options,
|
|
271
|
+
controlsColor: processColor(options.controlsColor),
|
|
272
|
+
toolbarColor: processColor(options.toolbarColor),
|
|
273
|
+
secondaryToolbarColor: processColor(options.secondaryToolbarColor),
|
|
274
|
+
};
|
|
275
|
+
}
|
|
265
276
|
/* iOS <= 10 and Android polyfill for SFAuthenticationSession flow */
|
|
266
277
|
function _authSessionIsNativelySupported() {
|
|
267
278
|
if (Platform.OS === 'android') {
|
package/build/WebBrowser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebBrowser.js","sourceRoot":"","sources":["../src/WebBrowser.ts"],"names":[],"mappings":"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","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\nimport { AppState, AppStateStatus, Linking, Platform, EmitterSubscription } from 'react-native';\n\nimport ExponentWebBrowser from './ExpoWebBrowser';\nimport {\n RedirectEvent,\n WebBrowserAuthSessionResult,\n WebBrowserCompleteAuthSessionOptions,\n WebBrowserCompleteAuthSessionResult,\n WebBrowserCoolDownResult,\n WebBrowserCustomTabsResults,\n WebBrowserMayInitWithUrlResult,\n WebBrowserOpenOptions,\n WebBrowserRedirectResult,\n WebBrowserResult,\n WebBrowserResultType,\n WebBrowserWarmUpResult,\n WebBrowserWindowFeatures,\n WebBrowserPresentationStyle,\n AuthSessionOpenOptions,\n} from './WebBrowser.types';\n\nexport {\n WebBrowserAuthSessionResult,\n WebBrowserCompleteAuthSessionOptions,\n WebBrowserCompleteAuthSessionResult,\n WebBrowserCoolDownResult,\n WebBrowserCustomTabsResults,\n WebBrowserMayInitWithUrlResult,\n WebBrowserOpenOptions,\n WebBrowserRedirectResult,\n WebBrowserResult,\n WebBrowserResultType,\n WebBrowserWarmUpResult,\n WebBrowserWindowFeatures,\n WebBrowserPresentationStyle,\n AuthSessionOpenOptions,\n};\n\nconst emptyCustomTabsPackages: WebBrowserCustomTabsResults = {\n defaultBrowserPackage: undefined,\n preferredBrowserPackage: undefined,\n browserPackages: [],\n servicePackages: [],\n};\n\n// @needsAudit\n/**\n * Returns a list of applications package names supporting Custom Tabs, Custom Tabs\n * service, user chosen and preferred one. This may not be fully reliable, since it uses\n * `PackageManager.getResolvingActivities` under the hood. (For example, some browsers might not be\n * present in browserPackages list once another browser is set to default.)\n *\n * @return The promise which fulfils with [`WebBrowserCustomTabsResults`](#webbrowsercustomtabsresults) object.\n * @platform android\n */\nexport async function getCustomTabsSupportingBrowsersAsync(): Promise<WebBrowserCustomTabsResults> {\n if (!ExponentWebBrowser.getCustomTabsSupportingBrowsersAsync) {\n throw new UnavailabilityError('WebBrowser', 'getCustomTabsSupportingBrowsersAsync');\n }\n if (Platform.OS !== 'android') {\n return emptyCustomTabsPackages;\n } else {\n return await ExponentWebBrowser.getCustomTabsSupportingBrowsersAsync();\n }\n}\n\n// @needsAudit\n/**\n * This method calls `warmUp` method on [CustomTabsClient](https://developer.android.com/reference/android/support/customtabs/CustomTabsClient.html#warmup(long))\n * for specified package.\n *\n * @param browserPackage Package of browser to be warmed up. If not set, preferred browser will be warmed.\n *\n * @return A promise which fulfils with `WebBrowserWarmUpResult` object.\n * @platform android\n */\nexport async function warmUpAsync(browserPackage?: string): Promise<WebBrowserWarmUpResult> {\n if (!ExponentWebBrowser.warmUpAsync) {\n throw new UnavailabilityError('WebBrowser', 'warmUpAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.warmUpAsync(browserPackage);\n }\n}\n\n// @needsAudit\n/**\n * This method initiates (if needed) [CustomTabsSession](https://developer.android.com/reference/android/support/customtabs/CustomTabsSession.html#maylaunchurl)\n * and calls its `mayLaunchUrl` method for browser specified by the package.\n *\n * @param url The url of page that is likely to be loaded first when opening browser.\n * @param browserPackage Package of browser to be informed. If not set, preferred\n * browser will be used.\n *\n * @return A promise which fulfils with `WebBrowserMayInitWithUrlResult` object.\n * @platform android\n */\nexport async function mayInitWithUrlAsync(\n url: string,\n browserPackage?: string\n): Promise<WebBrowserMayInitWithUrlResult> {\n if (!ExponentWebBrowser.mayInitWithUrlAsync) {\n throw new UnavailabilityError('WebBrowser', 'mayInitWithUrlAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.mayInitWithUrlAsync(url, browserPackage);\n }\n}\n\n// @needsAudit\n/**\n * This methods removes all bindings to services created by [`warmUpAsync`](#webbrowserwarmupasyncbrowserpackage)\n * or [`mayInitWithUrlAsync`](#webbrowsermayinitwithurlasyncurl-browserpackage). You should call\n * this method once you don't need them to avoid potential memory leaks. However, those binding\n * would be cleared once your application is destroyed, which might be sufficient in most cases.\n *\n * @param browserPackage Package of browser to be cooled. If not set, preferred browser will be used.\n *\n * @return The promise which fulfils with ` WebBrowserCoolDownResult` when cooling is performed, or\n * an empty object when there was no connection to be dismissed.\n * @platform android\n */\nexport async function coolDownAsync(browserPackage?: string): Promise<WebBrowserCoolDownResult> {\n if (!ExponentWebBrowser.coolDownAsync) {\n throw new UnavailabilityError('WebBrowser', 'coolDownAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.coolDownAsync(browserPackage);\n }\n}\n\nlet browserLocked = false;\n\n// @needsAudit\n/**\n * Opens the url with Safari in a modal on iOS using [`SFSafariViewController`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller),\n * and Chrome in a new [custom tab](https://developer.chrome.com/multidevice/android/customtabs)\n * on Android. On iOS, the modal Safari will not share cookies with the system Safari. If you need\n * this, use [`openAuthSessionAsync`](#webbrowseropenauthsessionasyncurl-redirecturl-browserparams).\n *\n * @param url The url to open in the web browser.\n * @param browserParams A dictionary of key-value pairs.\n *\n * @return The promise behaves differently based on the platform.\n * On Android promise resolves with `{type: 'opened'}` if we were able to open browser.\n * On iOS:\n * - If the user closed the web browser, the Promise resolves with `{ type: 'cancel' }`.\n * - If the browser is closed using [`dismissBrowser`](#webbrowserdismissbrowser), the Promise resolves with `{ type: 'dismiss' }`.\n */\nexport async function openBrowserAsync(\n url: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise<WebBrowserResult> {\n if (!ExponentWebBrowser.openBrowserAsync) {\n throw new UnavailabilityError('WebBrowser', 'openBrowserAsync');\n }\n\n if (browserLocked) {\n // Prevent multiple sessions from running at the same time, WebBrowser doesn't\n // support it this makes the behavior predictable.\n if (__DEV__) {\n console.warn(\n 'Attempted to call WebBrowser.openBrowserAsync multiple times while already active. Only one WebBrowser controller can be active at any given time.'\n );\n }\n\n return { type: WebBrowserResultType.LOCKED };\n }\n browserLocked = true;\n\n let result: WebBrowserResult;\n try {\n result = await ExponentWebBrowser.openBrowserAsync(url, browserParams);\n } finally {\n // WebBrowser session complete, unset lock\n browserLocked = false;\n }\n\n return result;\n}\n\n// @needsAudit\n/**\n * Dismisses the presented web browser.\n *\n * @return The `void` on successful attempt, or throws error, if dismiss functionality is not avaiable.\n * @platform ios\n */\nexport function dismissBrowser(): void {\n if (!ExponentWebBrowser.dismissBrowser) {\n throw new UnavailabilityError('WebBrowser', 'dismissBrowser');\n }\n ExponentWebBrowser.dismissBrowser();\n}\n\n// @needsAudit\n/**\n * # On iOS:\n * Opens the url with Safari in a modal using `SFAuthenticationSession` on iOS 11 and greater,\n * and falling back on a `SFSafariViewController`. The user will be asked whether to allow the app\n * to authenticate using the given url.\n *\n * # On Android:\n * This will be done using a \"custom Chrome tabs\" browser, [AppState](../react-native/appstate/),\n * and [Linking](./linking/) APIs.\n *\n * # On web:\n * > This API can only be used in a secure environment (`https`). You can use expo `start:web --https`\n * to test this. Otherwise, an error with code [`ERR_WEB_BROWSER_CRYPTO`](#errwebbrowsercrypto) will be thrown.\n * This will use the browser's [`window.open()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) API.\n * - _Desktop_: This will create a new web popup window in the browser that can be closed later using `WebBrowser.maybeCompleteAuthSession()`.\n * - _Mobile_: This will open a new tab in the browser which can be closed using `WebBrowser.maybeCompleteAuthSession()`.\n *\n * How this works on web:\n * - A crypto state will be created for verifying the redirect.\n * - This means you need to run with `expo start:web --https`\n * - The state will be added to the window's `localstorage`. This ensures that auth cannot complete\n * unless it's done from a page running with the same origin as it was started.\n * Ex: if `openAuthSessionAsync` is invoked on `https://localhost:19006`, then `maybeCompleteAuthSession`\n * must be invoked on a page hosted from the origin `https://localhost:19006`. Using a different\n * website, or even a different host like `https://128.0.0.*:19006` for example will not work.\n * - A timer will be started to check for every 1000 milliseconds (1 second) to detect if the window\n * has been closed by the user. If this happens then a promise will resolve with `{ type: 'dismiss' }`.\n *\n * > On mobile web, Chrome and Safari will block any call to [`window.open()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/open)\n * which takes too long to fire after a user interaction. This method must be invoked immediately\n * after a user interaction. If the event is blocked, an error with code [`ERR_WEB_BROWSER_BLOCKED`](#errwebbrowserblocked) will be thrown.\n *\n * @param url The url to open in the web browser. This should be a login page.\n * @param redirectUrl _Optional_ - The url to deep link back into your app.\n * On web, this defaults to the output of [`Linking.createURL(\"\")`](./linking/#linkingcreateurlpath-namedparameters).\n * @param options _Optional_ - An object extending the [`WebBrowserOpenOptions`](#webbrowseropenoptions).\n * If there is no native AuthSession implementation available (which is the case on Android)\n * these params will be used in the browser polyfill. If there is a native AuthSession implementation,\n * these params will be ignored.\n *\n * @return\n * - If the user does not permit the application to authenticate with the given url, the Promise fulfills with `{ type: 'cancel' }` object.\n * - If the user closed the web browser, the Promise fulfills with `{ type: 'cancel' }` object.\n * - If the browser is closed using [`dismissBrowser`](#webbrowserdismissbrowser),\n * the Promise fulfills with `{ type: 'dismiss' }` object.\n */\nexport async function openAuthSessionAsync(\n url: string,\n redirectUrl?: string | null,\n options: AuthSessionOpenOptions = {}\n): Promise<WebBrowserAuthSessionResult> {\n if (_authSessionIsNativelySupported()) {\n if (!ExponentWebBrowser.openAuthSessionAsync) {\n throw new UnavailabilityError('WebBrowser', 'openAuthSessionAsync');\n }\n if (['ios', 'web'].includes(Platform.OS)) {\n return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl, options);\n }\n return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl);\n } else {\n return _openAuthSessionPolyfillAsync(url, redirectUrl, options);\n }\n}\n\n// @docsMissing\nexport function dismissAuthSession(): void {\n if (_authSessionIsNativelySupported()) {\n if (!ExponentWebBrowser.dismissAuthSession) {\n throw new UnavailabilityError('WebBrowser', 'dismissAuthSession');\n }\n ExponentWebBrowser.dismissAuthSession();\n } else {\n if (!ExponentWebBrowser.dismissBrowser) {\n throw new UnavailabilityError('WebBrowser', 'dismissAuthSession');\n }\n ExponentWebBrowser.dismissBrowser();\n }\n}\n\n// @needsAudit\n/**\n * Possibly completes an authentication session on web in a window popup. The method\n * should be invoked on the page that the window redirects to.\n *\n * @param options\n *\n * @return Returns an object with message about why the redirect failed or succeeded:\n *\n * If `type` is set to `failed`, the reason depends on the message:\n * - `Not supported on this platform`: If the platform doesn't support this method (iOS, Android).\n * - `Cannot use expo-web-browser in a non-browser environment`: If the code was executed in an SSR\n * or node environment.\n * - `No auth session is currently in progress`: (the cached state wasn't found in local storage).\n * This can happen if the window redirects to an origin (website) that is different to the initial\n * website origin. If this happens in development, it may be because the auth started on localhost\n * and finished on your computer port (Ex: `128.0.0.*`). This is controlled by the `redirectUrl`\n * and `returnUrl`.\n * - `Current URL \"<URL>\" and original redirect URL \"<URL>\" do not match`: This can occur when the\n * redirect URL doesn't match what was initial defined as the `returnUrl`. You can skip this test\n * in development by passing `{ skipRedirectCheck: true }` to the function.\n *\n * If `type` is set to `success`, the parent window will attempt to close the child window immediately.\n *\n * If the error `ERR_WEB_BROWSER_REDIRECT` was thrown, it may mean that the parent window was\n * reloaded before the auth was completed. In this case you'll need to close the child window manually.\n *\n * @platform web\n */\nexport function maybeCompleteAuthSession(\n options: WebBrowserCompleteAuthSessionOptions = {}\n): WebBrowserCompleteAuthSessionResult {\n if (ExponentWebBrowser.maybeCompleteAuthSession) {\n return ExponentWebBrowser.maybeCompleteAuthSession(options);\n }\n return { type: 'failed', message: 'Not supported on this platform' };\n}\n\n/* iOS <= 10 and Android polyfill for SFAuthenticationSession flow */\n\nfunction _authSessionIsNativelySupported(): boolean {\n if (Platform.OS === 'android') {\n return false;\n } else if (Platform.OS === 'web') {\n return true;\n }\n\n const versionNumber = parseInt(String(Platform.Version), 10);\n return versionNumber >= 11;\n}\n\nlet _redirectSubscription: EmitterSubscription | null = null;\n\n/*\n * openBrowserAsync on Android doesn't wait until closed, so we need to polyfill\n * it with AppState\n */\n\n// Store the `resolve` function from a Promise to fire when the AppState\n// returns to active\nlet _onWebBrowserCloseAndroid: null | (() => void) = null;\n\n// If the initial AppState.currentState is null, we assume that the first call to\n// AppState#change event is not actually triggered by a real change,\n// is triggered instead by the bridge capturing the current state\n// (https://reactnative.dev/docs/appstate#basic-usage)\nlet _isAppStateAvailable: boolean = AppState.currentState !== null;\nfunction _onAppStateChangeAndroid(state: AppStateStatus) {\n if (!_isAppStateAvailable) {\n _isAppStateAvailable = true;\n return;\n }\n\n if (state === 'active' && _onWebBrowserCloseAndroid) {\n _onWebBrowserCloseAndroid();\n }\n}\n\nasync function _openBrowserAndWaitAndroidAsync(\n startUrl: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise<WebBrowserResult> {\n const appStateChangedToActive = new Promise<void>((resolve) => {\n _onWebBrowserCloseAndroid = resolve;\n });\n const stateChangeSubscription = AppState.addEventListener('change', _onAppStateChangeAndroid);\n\n let result: WebBrowserResult = { type: WebBrowserResultType.CANCEL };\n let type: string | null = null;\n\n try {\n ({ type } = await openBrowserAsync(startUrl, browserParams));\n } catch (e) {\n stateChangeSubscription.remove();\n _onWebBrowserCloseAndroid = null;\n throw e;\n }\n\n if (type === 'opened') {\n await appStateChangedToActive;\n result = { type: WebBrowserResultType.DISMISS };\n }\n\n stateChangeSubscription.remove();\n _onWebBrowserCloseAndroid = null;\n return result;\n}\n\nasync function _openAuthSessionPolyfillAsync(\n startUrl: string,\n returnUrl: string | null | undefined,\n browserParams: WebBrowserOpenOptions = {}\n): Promise<WebBrowserAuthSessionResult> {\n if (_redirectSubscription) {\n throw new Error(\n `The WebBrowser's auth session is in an invalid state with a redirect handler set when it should not be`\n );\n }\n\n if (_onWebBrowserCloseAndroid) {\n throw new Error(`WebBrowser is already open, only one can be open at a time`);\n }\n\n try {\n if (Platform.OS === 'android') {\n return await Promise.race([\n _openBrowserAndWaitAndroidAsync(startUrl, browserParams),\n _waitForRedirectAsync(returnUrl),\n ]);\n } else {\n return await Promise.race([\n openBrowserAsync(startUrl, browserParams),\n _waitForRedirectAsync(returnUrl),\n ]);\n }\n } finally {\n // We can't dismiss the browser on Android, only call this when it's available.\n // Users on Android need to manually press the 'x' button in Chrome Custom Tabs, sadly.\n if (ExponentWebBrowser.dismissBrowser) {\n ExponentWebBrowser.dismissBrowser();\n }\n\n _stopWaitingForRedirect();\n }\n}\n\nfunction _stopWaitingForRedirect() {\n if (!_redirectSubscription) {\n throw new Error(\n `The WebBrowser auth session is in an invalid state with no redirect handler when one should be set`\n );\n }\n\n _redirectSubscription.remove();\n _redirectSubscription = null;\n}\n\nfunction _waitForRedirectAsync(\n returnUrl: string | null | undefined\n): Promise<WebBrowserRedirectResult> {\n // Note that this Promise never resolves when `returnUrl` is nullish\n return new Promise((resolve) => {\n const redirectHandler = (event: RedirectEvent) => {\n if (returnUrl && event.url.startsWith(returnUrl)) {\n resolve({ url: event.url, type: 'success' });\n }\n };\n\n _redirectSubscription = Linking.addEventListener('url', redirectHandler);\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"WebBrowser.js","sourceRoot":"","sources":["../src/WebBrowser.ts"],"names":[],"mappings":"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","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\nimport {\n AppState,\n AppStateStatus,\n Linking,\n Platform,\n EmitterSubscription,\n processColor,\n} from 'react-native';\n\nimport ExponentWebBrowser from './ExpoWebBrowser';\nimport {\n RedirectEvent,\n WebBrowserAuthSessionResult,\n WebBrowserCompleteAuthSessionOptions,\n WebBrowserCompleteAuthSessionResult,\n WebBrowserCoolDownResult,\n WebBrowserCustomTabsResults,\n WebBrowserMayInitWithUrlResult,\n WebBrowserOpenOptions,\n WebBrowserRedirectResult,\n WebBrowserResult,\n WebBrowserResultType,\n WebBrowserWarmUpResult,\n WebBrowserWindowFeatures,\n WebBrowserPresentationStyle,\n AuthSessionOpenOptions,\n} from './WebBrowser.types';\n\nexport {\n WebBrowserAuthSessionResult,\n WebBrowserCompleteAuthSessionOptions,\n WebBrowserCompleteAuthSessionResult,\n WebBrowserCoolDownResult,\n WebBrowserCustomTabsResults,\n WebBrowserMayInitWithUrlResult,\n WebBrowserOpenOptions,\n WebBrowserRedirectResult,\n WebBrowserResult,\n WebBrowserResultType,\n WebBrowserWarmUpResult,\n WebBrowserWindowFeatures,\n WebBrowserPresentationStyle,\n AuthSessionOpenOptions,\n};\n\nconst emptyCustomTabsPackages: WebBrowserCustomTabsResults = {\n defaultBrowserPackage: undefined,\n preferredBrowserPackage: undefined,\n browserPackages: [],\n servicePackages: [],\n};\n\n// @needsAudit\n/**\n * Returns a list of applications package names supporting Custom Tabs, Custom Tabs\n * service, user chosen and preferred one. This may not be fully reliable, since it uses\n * `PackageManager.getResolvingActivities` under the hood. (For example, some browsers might not be\n * present in browserPackages list once another browser is set to default.)\n *\n * @return The promise which fulfils with [`WebBrowserCustomTabsResults`](#webbrowsercustomtabsresults) object.\n * @platform android\n */\nexport async function getCustomTabsSupportingBrowsersAsync(): Promise<WebBrowserCustomTabsResults> {\n if (!ExponentWebBrowser.getCustomTabsSupportingBrowsersAsync) {\n throw new UnavailabilityError('WebBrowser', 'getCustomTabsSupportingBrowsersAsync');\n }\n if (Platform.OS !== 'android') {\n return emptyCustomTabsPackages;\n } else {\n return await ExponentWebBrowser.getCustomTabsSupportingBrowsersAsync();\n }\n}\n\n// @needsAudit\n/**\n * This method calls `warmUp` method on [CustomTabsClient](https://developer.android.com/reference/android/support/customtabs/CustomTabsClient.html#warmup(long))\n * for specified package.\n *\n * @param browserPackage Package of browser to be warmed up. If not set, preferred browser will be warmed.\n *\n * @return A promise which fulfils with `WebBrowserWarmUpResult` object.\n * @platform android\n */\nexport async function warmUpAsync(browserPackage?: string): Promise<WebBrowserWarmUpResult> {\n if (!ExponentWebBrowser.warmUpAsync) {\n throw new UnavailabilityError('WebBrowser', 'warmUpAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.warmUpAsync(browserPackage);\n }\n}\n\n// @needsAudit\n/**\n * This method initiates (if needed) [CustomTabsSession](https://developer.android.com/reference/android/support/customtabs/CustomTabsSession.html#maylaunchurl)\n * and calls its `mayLaunchUrl` method for browser specified by the package.\n *\n * @param url The url of page that is likely to be loaded first when opening browser.\n * @param browserPackage Package of browser to be informed. If not set, preferred\n * browser will be used.\n *\n * @return A promise which fulfils with `WebBrowserMayInitWithUrlResult` object.\n * @platform android\n */\nexport async function mayInitWithUrlAsync(\n url: string,\n browserPackage?: string\n): Promise<WebBrowserMayInitWithUrlResult> {\n if (!ExponentWebBrowser.mayInitWithUrlAsync) {\n throw new UnavailabilityError('WebBrowser', 'mayInitWithUrlAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.mayInitWithUrlAsync(url, browserPackage);\n }\n}\n\n// @needsAudit\n/**\n * This methods removes all bindings to services created by [`warmUpAsync`](#webbrowserwarmupasyncbrowserpackage)\n * or [`mayInitWithUrlAsync`](#webbrowsermayinitwithurlasyncurl-browserpackage). You should call\n * this method once you don't need them to avoid potential memory leaks. However, those binding\n * would be cleared once your application is destroyed, which might be sufficient in most cases.\n *\n * @param browserPackage Package of browser to be cooled. If not set, preferred browser will be used.\n *\n * @return The promise which fulfils with ` WebBrowserCoolDownResult` when cooling is performed, or\n * an empty object when there was no connection to be dismissed.\n * @platform android\n */\nexport async function coolDownAsync(browserPackage?: string): Promise<WebBrowserCoolDownResult> {\n if (!ExponentWebBrowser.coolDownAsync) {\n throw new UnavailabilityError('WebBrowser', 'coolDownAsync');\n }\n if (Platform.OS !== 'android') {\n return {};\n } else {\n return await ExponentWebBrowser.coolDownAsync(browserPackage);\n }\n}\n\nlet browserLocked = false;\n\n// @needsAudit\n/**\n * Opens the url with Safari in a modal on iOS using [`SFSafariViewController`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller),\n * and Chrome in a new [custom tab](https://developer.chrome.com/multidevice/android/customtabs)\n * on Android. On iOS, the modal Safari will not share cookies with the system Safari. If you need\n * this, use [`openAuthSessionAsync`](#webbrowseropenauthsessionasyncurl-redirecturl-browserparams).\n *\n * @param url The url to open in the web browser.\n * @param browserParams A dictionary of key-value pairs.\n *\n * @return The promise behaves differently based on the platform.\n * On Android promise resolves with `{type: 'opened'}` if we were able to open browser.\n * On iOS:\n * - If the user closed the web browser, the Promise resolves with `{ type: 'cancel' }`.\n * - If the browser is closed using [`dismissBrowser`](#webbrowserdismissbrowser), the Promise resolves with `{ type: 'dismiss' }`.\n */\nexport async function openBrowserAsync(\n url: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise<WebBrowserResult> {\n if (!ExponentWebBrowser.openBrowserAsync) {\n throw new UnavailabilityError('WebBrowser', 'openBrowserAsync');\n }\n\n if (browserLocked) {\n // Prevent multiple sessions from running at the same time, WebBrowser doesn't\n // support it this makes the behavior predictable.\n if (__DEV__) {\n console.warn(\n 'Attempted to call WebBrowser.openBrowserAsync multiple times while already active. Only one WebBrowser controller can be active at any given time.'\n );\n }\n\n return { type: WebBrowserResultType.LOCKED };\n }\n browserLocked = true;\n\n let result: WebBrowserResult;\n try {\n result = await ExponentWebBrowser.openBrowserAsync(url, _processOptions(browserParams));\n } finally {\n // WebBrowser session complete, unset lock\n browserLocked = false;\n }\n\n return result;\n}\n\n// @needsAudit\n/**\n * Dismisses the presented web browser.\n *\n * @return The `void` on successful attempt, or throws error, if dismiss functionality is not avaiable.\n * @platform ios\n */\nexport function dismissBrowser(): void {\n if (!ExponentWebBrowser.dismissBrowser) {\n throw new UnavailabilityError('WebBrowser', 'dismissBrowser');\n }\n ExponentWebBrowser.dismissBrowser();\n}\n\n// @needsAudit\n/**\n * # On iOS:\n * Opens the url with Safari in a modal using `ASWebAuthenticationSession`. The user will be asked\n * whether to allow the app to authenticate using the given url.\n * To handle redirection back to the mobile application, the redirect URI set in the authentication server\n * has to use the protocol provided as the scheme in **app.json** [`expo.scheme`](./../config/app/#scheme)\n * e.g. `demo://` not `https://` protocol.\n * Using `Linking.addEventListener` is not needed and can have side effects.\n *\n * # On Android:\n * This will be done using a \"custom Chrome tabs\" browser, [AppState](../react-native/appstate/),\n * and [Linking](./linking/) APIs.\n *\n * # On web:\n * > This API can only be used in a secure environment (`https`). You can use expo `start:web --https`\n * to test this. Otherwise, an error with code [`ERR_WEB_BROWSER_CRYPTO`](#errwebbrowsercrypto) will be thrown.\n * This will use the browser's [`window.open()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) API.\n * - _Desktop_: This will create a new web popup window in the browser that can be closed later using `WebBrowser.maybeCompleteAuthSession()`.\n * - _Mobile_: This will open a new tab in the browser which can be closed using `WebBrowser.maybeCompleteAuthSession()`.\n *\n * How this works on web:\n * - A crypto state will be created for verifying the redirect.\n * - This means you need to run with `npx expo start --https`\n * - The state will be added to the window's `localstorage`. This ensures that auth cannot complete\n * unless it's done from a page running with the same origin as it was started.\n * Ex: if `openAuthSessionAsync` is invoked on `https://localhost:19006`, then `maybeCompleteAuthSession`\n * must be invoked on a page hosted from the origin `https://localhost:19006`. Using a different\n * website, or even a different host like `https://128.0.0.*:19006` for example will not work.\n * - A timer will be started to check for every 1000 milliseconds (1 second) to detect if the window\n * has been closed by the user. If this happens then a promise will resolve with `{ type: 'dismiss' }`.\n *\n * > On mobile web, Chrome and Safari will block any call to [`window.open()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/open)\n * which takes too long to fire after a user interaction. This method must be invoked immediately\n * after a user interaction. If the event is blocked, an error with code [`ERR_WEB_BROWSER_BLOCKED`](#errwebbrowserblocked) will be thrown.\n *\n * @param url The url to open in the web browser. This should be a login page.\n * @param redirectUrl _Optional_ - The url to deep link back into your app.\n * On web, this defaults to the output of [`Linking.createURL(\"\")`](./linking/#linkingcreateurlpath-namedparameters).\n * @param options _Optional_ - An object extending the [`WebBrowserOpenOptions`](#webbrowseropenoptions).\n * If there is no native AuthSession implementation available (which is the case on Android)\n * these params will be used in the browser polyfill. If there is a native AuthSession implementation,\n * these params will be ignored.\n *\n * @return\n * - If the user does not permit the application to authenticate with the given url, the Promise fulfills with `{ type: 'cancel' }` object.\n * - If the user closed the web browser, the Promise fulfills with `{ type: 'cancel' }` object.\n * - If the browser is closed using [`dismissBrowser`](#webbrowserdismissbrowser),\n * the Promise fulfills with `{ type: 'dismiss' }` object.\n */\nexport async function openAuthSessionAsync(\n url: string,\n redirectUrl?: string | null,\n options: AuthSessionOpenOptions = {}\n): Promise<WebBrowserAuthSessionResult> {\n if (_authSessionIsNativelySupported()) {\n if (!ExponentWebBrowser.openAuthSessionAsync) {\n throw new UnavailabilityError('WebBrowser', 'openAuthSessionAsync');\n }\n if (['ios', 'web'].includes(Platform.OS)) {\n return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl, _processOptions(options));\n }\n return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl);\n } else {\n return _openAuthSessionPolyfillAsync(url, redirectUrl, options);\n }\n}\n\n// @docsMissing\nexport function dismissAuthSession(): void {\n if (_authSessionIsNativelySupported()) {\n if (!ExponentWebBrowser.dismissAuthSession) {\n throw new UnavailabilityError('WebBrowser', 'dismissAuthSession');\n }\n ExponentWebBrowser.dismissAuthSession();\n } else {\n if (!ExponentWebBrowser.dismissBrowser) {\n throw new UnavailabilityError('WebBrowser', 'dismissAuthSession');\n }\n ExponentWebBrowser.dismissBrowser();\n }\n}\n\n// @needsAudit\n/**\n * Possibly completes an authentication session on web in a window popup. The method\n * should be invoked on the page that the window redirects to.\n *\n * @param options\n *\n * @return Returns an object with message about why the redirect failed or succeeded:\n *\n * If `type` is set to `failed`, the reason depends on the message:\n * - `Not supported on this platform`: If the platform doesn't support this method (iOS, Android).\n * - `Cannot use expo-web-browser in a non-browser environment`: If the code was executed in an SSR\n * or node environment.\n * - `No auth session is currently in progress`: (the cached state wasn't found in local storage).\n * This can happen if the window redirects to an origin (website) that is different to the initial\n * website origin. If this happens in development, it may be because the auth started on localhost\n * and finished on your computer port (Ex: `128.0.0.*`). This is controlled by the `redirectUrl`\n * and `returnUrl`.\n * - `Current URL \"<URL>\" and original redirect URL \"<URL>\" do not match`: This can occur when the\n * redirect URL doesn't match what was initial defined as the `returnUrl`. You can skip this test\n * in development by passing `{ skipRedirectCheck: true }` to the function.\n *\n * If `type` is set to `success`, the parent window will attempt to close the child window immediately.\n *\n * If the error `ERR_WEB_BROWSER_REDIRECT` was thrown, it may mean that the parent window was\n * reloaded before the auth was completed. In this case you'll need to close the child window manually.\n *\n * @platform web\n */\nexport function maybeCompleteAuthSession(\n options: WebBrowserCompleteAuthSessionOptions = {}\n): WebBrowserCompleteAuthSessionResult {\n if (ExponentWebBrowser.maybeCompleteAuthSession) {\n return ExponentWebBrowser.maybeCompleteAuthSession(options);\n }\n return { type: 'failed', message: 'Not supported on this platform' };\n}\n\nfunction _processOptions(options: WebBrowserOpenOptions) {\n return {\n ...options,\n controlsColor: processColor(options.controlsColor),\n toolbarColor: processColor(options.toolbarColor),\n secondaryToolbarColor: processColor(options.secondaryToolbarColor),\n };\n}\n\n/* iOS <= 10 and Android polyfill for SFAuthenticationSession flow */\n\nfunction _authSessionIsNativelySupported(): boolean {\n if (Platform.OS === 'android') {\n return false;\n } else if (Platform.OS === 'web') {\n return true;\n }\n\n const versionNumber = parseInt(String(Platform.Version), 10);\n return versionNumber >= 11;\n}\n\nlet _redirectSubscription: EmitterSubscription | null = null;\n\n/*\n * openBrowserAsync on Android doesn't wait until closed, so we need to polyfill\n * it with AppState\n */\n\n// Store the `resolve` function from a Promise to fire when the AppState\n// returns to active\nlet _onWebBrowserCloseAndroid: null | (() => void) = null;\n\n// If the initial AppState.currentState is null, we assume that the first call to\n// AppState#change event is not actually triggered by a real change,\n// is triggered instead by the bridge capturing the current state\n// (https://reactnative.dev/docs/appstate#basic-usage)\nlet _isAppStateAvailable: boolean = AppState.currentState !== null;\nfunction _onAppStateChangeAndroid(state: AppStateStatus) {\n if (!_isAppStateAvailable) {\n _isAppStateAvailable = true;\n return;\n }\n\n if (state === 'active' && _onWebBrowserCloseAndroid) {\n _onWebBrowserCloseAndroid();\n }\n}\n\nasync function _openBrowserAndWaitAndroidAsync(\n startUrl: string,\n browserParams: WebBrowserOpenOptions = {}\n): Promise<WebBrowserResult> {\n const appStateChangedToActive = new Promise<void>((resolve) => {\n _onWebBrowserCloseAndroid = resolve;\n });\n const stateChangeSubscription = AppState.addEventListener('change', _onAppStateChangeAndroid);\n\n let result: WebBrowserResult = { type: WebBrowserResultType.CANCEL };\n let type: string | null = null;\n\n try {\n ({ type } = await openBrowserAsync(startUrl, browserParams));\n } catch (e) {\n stateChangeSubscription.remove();\n _onWebBrowserCloseAndroid = null;\n throw e;\n }\n\n if (type === 'opened') {\n await appStateChangedToActive;\n result = { type: WebBrowserResultType.DISMISS };\n }\n\n stateChangeSubscription.remove();\n _onWebBrowserCloseAndroid = null;\n return result;\n}\n\nasync function _openAuthSessionPolyfillAsync(\n startUrl: string,\n returnUrl: string | null | undefined,\n browserParams: WebBrowserOpenOptions = {}\n): Promise<WebBrowserAuthSessionResult> {\n if (_redirectSubscription) {\n throw new Error(\n `The WebBrowser's auth session is in an invalid state with a redirect handler set when it should not be`\n );\n }\n\n if (_onWebBrowserCloseAndroid) {\n throw new Error(`WebBrowser is already open, only one can be open at a time`);\n }\n\n try {\n if (Platform.OS === 'android') {\n return await Promise.race([\n _openBrowserAndWaitAndroidAsync(startUrl, browserParams),\n _waitForRedirectAsync(returnUrl),\n ]);\n } else {\n return await Promise.race([\n openBrowserAsync(startUrl, browserParams),\n _waitForRedirectAsync(returnUrl),\n ]);\n }\n } finally {\n // We can't dismiss the browser on Android, only call this when it's available.\n // Users on Android need to manually press the 'x' button in Chrome Custom Tabs, sadly.\n if (ExponentWebBrowser.dismissBrowser) {\n ExponentWebBrowser.dismissBrowser();\n }\n\n _stopWaitingForRedirect();\n }\n}\n\nfunction _stopWaitingForRedirect() {\n if (!_redirectSubscription) {\n throw new Error(\n `The WebBrowser auth session is in an invalid state with no redirect handler when one should be set`\n );\n }\n\n _redirectSubscription.remove();\n _redirectSubscription = null;\n}\n\nfunction _waitForRedirectAsync(\n returnUrl: string | null | undefined\n): Promise<WebBrowserRedirectResult> {\n // Note that this Promise never resolves when `returnUrl` is nullish\n return new Promise((resolve) => {\n const redirectHandler = (event: RedirectEvent) => {\n if (returnUrl && event.url.startsWith(returnUrl)) {\n resolve({ url: event.url, type: 'success' });\n }\n };\n\n _redirectSubscription = Linking.addEventListener('url', redirectHandler);\n });\n}\n"]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type RedirectEvent = {
|
|
2
2
|
url: string;
|
|
3
3
|
};
|
|
4
|
-
export
|
|
5
|
-
export
|
|
4
|
+
export type WebBrowserWindowFeatures = Record<string, number | boolean | string>;
|
|
5
|
+
export type WebBrowserOpenOptions = {
|
|
6
6
|
/**
|
|
7
|
-
* Color of the toolbar
|
|
7
|
+
* Color of the toolbar. Supports React Native [color formats](https://reactnative.dev/docs/colors).
|
|
8
8
|
*/
|
|
9
9
|
toolbarColor?: string;
|
|
10
10
|
/**
|
|
@@ -18,7 +18,7 @@ export declare type WebBrowserOpenOptions = {
|
|
|
18
18
|
*/
|
|
19
19
|
enableBarCollapsing?: boolean;
|
|
20
20
|
/**
|
|
21
|
-
* Color of the secondary toolbar
|
|
21
|
+
* Color of the secondary toolbar. Supports React Native [color formats](https://reactnative.dev/docs/colors).
|
|
22
22
|
* @platform android
|
|
23
23
|
*/
|
|
24
24
|
secondaryToolbarColor?: string;
|
|
@@ -47,7 +47,7 @@ export declare type WebBrowserOpenOptions = {
|
|
|
47
47
|
*/
|
|
48
48
|
createTask?: boolean;
|
|
49
49
|
/**
|
|
50
|
-
* Tint color for controls in SKSafariViewController
|
|
50
|
+
* Tint color for controls in SKSafariViewController. Supports React Native [color formats](https://reactnative.dev/docs/colors).
|
|
51
51
|
* @platform ios
|
|
52
52
|
*/
|
|
53
53
|
controlsColor?: string;
|
|
@@ -83,7 +83,7 @@ export declare type WebBrowserOpenOptions = {
|
|
|
83
83
|
* If there is no native AuthSession implementation available (which is the case on Android) the params inherited from
|
|
84
84
|
* [`WebBrowserOpenOptions`](#webbrowseropenoptions) will be used in the browser polyfill. Otherwise, the browser parameters will be ignored.
|
|
85
85
|
*/
|
|
86
|
-
export
|
|
86
|
+
export type AuthSessionOpenOptions = WebBrowserOpenOptions & {
|
|
87
87
|
/**
|
|
88
88
|
* Determines whether the session should ask the browser for a private authentication session.
|
|
89
89
|
* Set this to `true` to request that the browser doesnβt share cookies or other browsing data between the authentication session and the userβs normal browser session.
|
|
@@ -94,8 +94,8 @@ export declare type AuthSessionOpenOptions = WebBrowserOpenOptions & {
|
|
|
94
94
|
*/
|
|
95
95
|
preferEphemeralSession?: boolean;
|
|
96
96
|
};
|
|
97
|
-
export
|
|
98
|
-
export
|
|
97
|
+
export type WebBrowserAuthSessionResult = WebBrowserRedirectResult | WebBrowserResult;
|
|
98
|
+
export type WebBrowserCustomTabsResults = {
|
|
99
99
|
/**
|
|
100
100
|
* Default package chosen by user, `null` if there is no such packages. Also `null` usually means,
|
|
101
101
|
* that user will be prompted to choose from available packages.
|
|
@@ -178,32 +178,32 @@ export declare enum WebBrowserPresentationStyle {
|
|
|
178
178
|
*/
|
|
179
179
|
AUTOMATIC = "automatic"
|
|
180
180
|
}
|
|
181
|
-
export
|
|
181
|
+
export type WebBrowserResult = {
|
|
182
182
|
/**
|
|
183
183
|
* Type of the result.
|
|
184
184
|
*/
|
|
185
185
|
type: WebBrowserResultType;
|
|
186
186
|
};
|
|
187
|
-
export
|
|
187
|
+
export type WebBrowserRedirectResult = {
|
|
188
188
|
/**
|
|
189
189
|
* Type of the result.
|
|
190
190
|
*/
|
|
191
191
|
type: 'success';
|
|
192
192
|
url: string;
|
|
193
193
|
};
|
|
194
|
-
export
|
|
194
|
+
export type ServiceActionResult = {
|
|
195
195
|
servicePackage?: string;
|
|
196
196
|
};
|
|
197
|
-
export
|
|
198
|
-
export
|
|
199
|
-
export
|
|
200
|
-
export
|
|
197
|
+
export type WebBrowserMayInitWithUrlResult = ServiceActionResult;
|
|
198
|
+
export type WebBrowserWarmUpResult = ServiceActionResult;
|
|
199
|
+
export type WebBrowserCoolDownResult = ServiceActionResult;
|
|
200
|
+
export type WebBrowserCompleteAuthSessionOptions = {
|
|
201
201
|
/**
|
|
202
202
|
* Attempt to close the window without checking to see if the auth redirect matches the cached redirect URL.
|
|
203
203
|
*/
|
|
204
204
|
skipRedirectCheck?: boolean;
|
|
205
205
|
};
|
|
206
|
-
export
|
|
206
|
+
export type WebBrowserCompleteAuthSessionResult = {
|
|
207
207
|
/**
|
|
208
208
|
* Type of the result.
|
|
209
209
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebBrowser.types.d.ts","sourceRoot":"","sources":["../src/WebBrowser.types.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"WebBrowser.types.d.ts","sourceRoot":"","sources":["../src/WebBrowser.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebBrowser.types.js","sourceRoot":"","sources":["../src/WebBrowser.types.ts"],"names":[],"mappings":"AAoIA,2BAA2B;AAC3B,MAAM,CAAN,IAAY,oBAcX;AAdD,WAAY,oBAAoB;IAC9B;;OAEG;IACH,yCAAiB,CAAA;IACjB;;OAEG;IACH,2CAAmB,CAAA;IACnB;;OAEG;IACH,yCAAiB,CAAA;IACjB,yCAAiB,CAAA;AACnB,CAAC,EAdW,oBAAoB,KAApB,oBAAoB,QAc/B;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAN,IAAY,2BAoCX;AApCD,WAAY,2BAA2B;IACrC;;OAEG;IACH,yDAA0B,CAAA;IAC1B;;OAEG;IACH,uDAAwB,CAAA;IACxB;;OAEG;IACH,uDAAwB,CAAA;IACxB;;OAEG;IACH,iEAAkC,CAAA;IAClC;;OAEG;IACH,kEAAmC,CAAA;IACnC;;OAEG;IACH,0EAA2C,CAAA;IAC3C;;OAEG;IACH,kDAAmB,CAAA;IACnB;;;;;OAKG;IACH,sDAAuB,CAAA;AACzB,CAAC,EApCW,2BAA2B,KAA3B,2BAA2B,QAoCtC","sourcesContent":["export type RedirectEvent = {\n url: string;\n};\n\n// @needsAudit @docsMissing\nexport type WebBrowserWindowFeatures = Record<string, number | boolean | string>;\n\n// @needsAudit\nexport type WebBrowserOpenOptions = {\n /**\n * Color of the toolbar
|
|
1
|
+
{"version":3,"file":"WebBrowser.types.js","sourceRoot":"","sources":["../src/WebBrowser.types.ts"],"names":[],"mappings":"AAoIA,2BAA2B;AAC3B,MAAM,CAAN,IAAY,oBAcX;AAdD,WAAY,oBAAoB;IAC9B;;OAEG;IACH,yCAAiB,CAAA;IACjB;;OAEG;IACH,2CAAmB,CAAA;IACnB;;OAEG;IACH,yCAAiB,CAAA;IACjB,yCAAiB,CAAA;AACnB,CAAC,EAdW,oBAAoB,KAApB,oBAAoB,QAc/B;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAN,IAAY,2BAoCX;AApCD,WAAY,2BAA2B;IACrC;;OAEG;IACH,yDAA0B,CAAA;IAC1B;;OAEG;IACH,uDAAwB,CAAA;IACxB;;OAEG;IACH,uDAAwB,CAAA;IACxB;;OAEG;IACH,iEAAkC,CAAA;IAClC;;OAEG;IACH,kEAAmC,CAAA;IACnC;;OAEG;IACH,0EAA2C,CAAA;IAC3C;;OAEG;IACH,kDAAmB,CAAA;IACnB;;;;;OAKG;IACH,sDAAuB,CAAA;AACzB,CAAC,EApCW,2BAA2B,KAA3B,2BAA2B,QAoCtC","sourcesContent":["export type RedirectEvent = {\n url: string;\n};\n\n// @needsAudit @docsMissing\nexport type WebBrowserWindowFeatures = Record<string, number | boolean | string>;\n\n// @needsAudit\nexport type WebBrowserOpenOptions = {\n /**\n * Color of the toolbar. Supports React Native [color formats](https://reactnative.dev/docs/colors).\n */\n toolbarColor?: string;\n /**\n * Package name of a browser to be used to handle Custom Tabs. List of\n * available packages is to be queried by [`getCustomTabsSupportingBrowsers`](#webbrowsergetcustomtabssupportingbrowsersasync) method.\n * @platform android\n */\n browserPackage?: string;\n /**\n * A boolean determining whether the toolbar should be hiding when a user scrolls the website.\n */\n enableBarCollapsing?: boolean;\n /**\n * Color of the secondary toolbar. Supports React Native [color formats](https://reactnative.dev/docs/colors).\n * @platform android\n */\n secondaryToolbarColor?: string;\n /**\n * A boolean determining whether the browser should show the title of website on the toolbar.\n * @platform android\n */\n showTitle?: boolean;\n /**\n * A boolean determining whether a default share item should be added to the menu.\n * @platform android\n */\n enableDefaultShareMenuItem?: boolean;\n /**\n * A boolean determining whether browsed website should be shown as separate\n * entry in Android recents/multitasking view. Requires `createTask` to be `true` (default).\n * @default false\n * @platform android\n */\n showInRecents?: boolean;\n /**\n * A boolean determining whether the browser should open in a new task or in\n * the same task as your app.\n * @default true\n * @platform android\n */\n createTask?: boolean;\n /**\n * Tint color for controls in SKSafariViewController. Supports React Native [color formats](https://reactnative.dev/docs/colors).\n * @platform ios\n */\n controlsColor?: string;\n /**\n * The style of the dismiss button. Should be one of: `done`, `close`, or `cancel`.\n * @platform ios\n */\n dismissButtonStyle?: 'done' | 'close' | 'cancel';\n /**\n * A boolean determining whether Safari should enter Reader mode, if it is available.\n * @platform ios\n */\n readerMode?: boolean;\n /**\n * The [presentation style](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621355-modalpresentationstyle)\n * of the browser window.\n * @default WebBrowser.WebBrowserPresentationStyle.OverFullScreen\n * @platform ios\n */\n presentationStyle?: WebBrowserPresentationStyle;\n /**\n * Name to assign to the popup window.\n * @platform web\n */\n windowName?: string;\n /**\n * Features to use with `window.open()`.\n * @platform web\n */\n windowFeatures?: string | WebBrowserWindowFeatures;\n};\n\n/**\n * If there is no native AuthSession implementation available (which is the case on Android) the params inherited from\n * [`WebBrowserOpenOptions`](#webbrowseropenoptions) will be used in the browser polyfill. Otherwise, the browser parameters will be ignored.\n */\nexport type AuthSessionOpenOptions = WebBrowserOpenOptions & {\n /**\n * Determines whether the session should ask the browser for a private authentication session.\n * Set this to `true` to request that the browser doesnβt share cookies or other browsing data between the authentication session and the userβs normal browser session.\n * Whether the request is honored depends on the userβs default web browser.\n *\n * @default false\n * @platform ios 13+\n */\n preferEphemeralSession?: boolean;\n};\n\nexport type WebBrowserAuthSessionResult = WebBrowserRedirectResult | WebBrowserResult;\n\n// @needsAudit\nexport type WebBrowserCustomTabsResults = {\n /**\n * Default package chosen by user, `null` if there is no such packages. Also `null` usually means,\n * that user will be prompted to choose from available packages.\n */\n defaultBrowserPackage?: string;\n /**\n * Package preferred by `CustomTabsClient` to be used to handle Custom Tabs. It favors browser\n * chosen by user as default, as long as it is present on both `browserPackages` and\n * `servicePackages` lists. Only such browsers are considered as fully supporting Custom Tabs.\n * It might be `null` when there is no such browser installed or when default browser is not in\n * `servicePackages` list.\n */\n preferredBrowserPackage?: string;\n /**\n * All packages recognized by `PackageManager` as capable of handling Custom Tabs. Empty array\n * means there is no supporting browsers on device.\n */\n browserPackages: string[];\n /**\n * All packages recognized by `PackageManager` as capable of handling Custom Tabs Service.\n * This service is used by [`warmUpAsync`](#webbrowserwarmupasyncbrowserpackage), [`mayInitWithUrlAsync`](#webbrowsermayinitwithurlasyncurl-browserpackage)\n * and [`coolDownAsync`](#webbrowsercooldownasyncbrowserpackage).\n */\n servicePackages: string[];\n};\n\n// @needsAudit @docsMissing\nexport enum WebBrowserResultType {\n /**\n * @platform ios\n */\n CANCEL = 'cancel',\n /**\n * @platform ios\n */\n DISMISS = 'dismiss',\n /**\n * @platform android\n */\n OPENED = 'opened',\n LOCKED = 'locked',\n}\n\n// @needsAudit\n/**\n * A browser presentation style. Its values are directly mapped to the [`UIModalPresentationStyle`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621355-modalpresentationstyle).\n *\n * @platform ios\n */\nexport enum WebBrowserPresentationStyle {\n /**\n * A presentation style in which the presented browser covers the screen.\n */\n FULL_SCREEN = 'fullScreen',\n /**\n * A presentation style that partially covers the underlying content.\n */\n PAGE_SHEET = 'pageSheet',\n /**\n * A presentation style that displays the browser centered in the screen.\n */\n FORM_SHEET = 'formSheet',\n /**\n * A presentation style where the browser is displayed over the app's content.\n */\n CURRENT_CONTEXT = 'currentContext',\n /**\n * A presentation style in which the browser view covers the screen.\n */\n OVER_FULL_SCREEN = 'overFullScreen',\n /**\n * A presentation style where the browser is displayed over the app's content.\n */\n OVER_CURRENT_CONTEXT = 'overCurrentContext',\n /**\n * A presentation style where the browser is displayed in a popover view.\n */\n POPOVER = 'popover',\n /**\n * The default presentation style chosen by the system.\n * On older iOS versions, falls back to `WebBrowserPresentationStyle.FullScreen`.\n *\n * @platform ios 13+\n */\n AUTOMATIC = 'automatic',\n}\n\n// @needsAudit\nexport type WebBrowserResult = {\n /**\n * Type of the result.\n */\n type: WebBrowserResultType;\n};\n\n// @needsAudit @docsMissing\nexport type WebBrowserRedirectResult = {\n /**\n * Type of the result.\n */\n type: 'success';\n url: string;\n};\n\nexport type ServiceActionResult = {\n servicePackage?: string;\n};\n\nexport type WebBrowserMayInitWithUrlResult = ServiceActionResult;\nexport type WebBrowserWarmUpResult = ServiceActionResult;\nexport type WebBrowserCoolDownResult = ServiceActionResult;\n\n// @needsAudit\nexport type WebBrowserCompleteAuthSessionOptions = {\n /**\n * Attempt to close the window without checking to see if the auth redirect matches the cached redirect URL.\n */\n skipRedirectCheck?: boolean;\n};\n\n// @needsAudit\nexport type WebBrowserCompleteAuthSessionResult = {\n /**\n * Type of the result.\n */\n type: 'success' | 'failed';\n /**\n * Additional description or reasoning of the result.\n */\n message: string;\n};\n"]}
|
|
@@ -10,7 +10,7 @@ Pod::Spec.new do |s|
|
|
|
10
10
|
s.license = package['license']
|
|
11
11
|
s.author = package['author']
|
|
12
12
|
s.homepage = package['homepage']
|
|
13
|
-
s.platform = :ios, '
|
|
13
|
+
s.platform = :ios, '13.0'
|
|
14
14
|
s.swift_version = '5.4'
|
|
15
15
|
s.source = { git: 'https://github.com/expo/expo.git' }
|
|
16
16
|
s.static_framework = true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-web-browser",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.1.0",
|
|
4
4
|
"description": "Provides access to the system's web browser and supports handling redirects. On iOS, it uses SFSafariViewController or SFAuthenticationSession, depending on the method you call, and on Android it uses ChromeCustomTabs. As of iOS 11, SFSafariViewController no longer shares cookies with Safari, so if you are using WebBrowser for authentication you will want to use WebBrowser.openAuthSessionAsync, and if you just want to open a webpage (such as your app privacy policy), then use WebBrowser.openBrowserAsync.",
|
|
5
5
|
"main": "build/WebBrowser.js",
|
|
6
6
|
"types": "build/WebBrowser.d.ts",
|
|
@@ -36,13 +36,14 @@
|
|
|
36
36
|
"preset": "expo-module-scripts"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"compare-urls": "^2.0.0"
|
|
39
|
+
"compare-urls": "^2.0.0",
|
|
40
|
+
"url": "^0.11.0"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
|
-
"expo-module-scripts": "^
|
|
43
|
+
"expo-module-scripts": "^3.0.0"
|
|
43
44
|
},
|
|
44
45
|
"peerDependencies": {
|
|
45
46
|
"expo": "*"
|
|
46
47
|
},
|
|
47
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "1815e2eaad8c753588c7b1eb74420174a28e01f4"
|
|
48
49
|
}
|
package/src/WebBrowser.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { UnavailabilityError } from 'expo-modules-core';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AppState,
|
|
4
|
+
AppStateStatus,
|
|
5
|
+
Linking,
|
|
6
|
+
Platform,
|
|
7
|
+
EmitterSubscription,
|
|
8
|
+
processColor,
|
|
9
|
+
} from 'react-native';
|
|
3
10
|
|
|
4
11
|
import ExponentWebBrowser from './ExpoWebBrowser';
|
|
5
12
|
import {
|
|
@@ -177,7 +184,7 @@ export async function openBrowserAsync(
|
|
|
177
184
|
|
|
178
185
|
let result: WebBrowserResult;
|
|
179
186
|
try {
|
|
180
|
-
result = await ExponentWebBrowser.openBrowserAsync(url, browserParams);
|
|
187
|
+
result = await ExponentWebBrowser.openBrowserAsync(url, _processOptions(browserParams));
|
|
181
188
|
} finally {
|
|
182
189
|
// WebBrowser session complete, unset lock
|
|
183
190
|
browserLocked = false;
|
|
@@ -203,9 +210,12 @@ export function dismissBrowser(): void {
|
|
|
203
210
|
// @needsAudit
|
|
204
211
|
/**
|
|
205
212
|
* # On iOS:
|
|
206
|
-
* Opens the url with Safari in a modal using `
|
|
207
|
-
*
|
|
208
|
-
* to
|
|
213
|
+
* Opens the url with Safari in a modal using `ASWebAuthenticationSession`. The user will be asked
|
|
214
|
+
* whether to allow the app to authenticate using the given url.
|
|
215
|
+
* To handle redirection back to the mobile application, the redirect URI set in the authentication server
|
|
216
|
+
* has to use the protocol provided as the scheme in **app.json** [`expo.scheme`](./../config/app/#scheme)
|
|
217
|
+
* e.g. `demo://` not `https://` protocol.
|
|
218
|
+
* Using `Linking.addEventListener` is not needed and can have side effects.
|
|
209
219
|
*
|
|
210
220
|
* # On Android:
|
|
211
221
|
* This will be done using a "custom Chrome tabs" browser, [AppState](../react-native/appstate/),
|
|
@@ -220,7 +230,7 @@ export function dismissBrowser(): void {
|
|
|
220
230
|
*
|
|
221
231
|
* How this works on web:
|
|
222
232
|
* - A crypto state will be created for verifying the redirect.
|
|
223
|
-
* - This means you need to run with `expo start
|
|
233
|
+
* - This means you need to run with `npx expo start --https`
|
|
224
234
|
* - The state will be added to the window's `localstorage`. This ensures that auth cannot complete
|
|
225
235
|
* unless it's done from a page running with the same origin as it was started.
|
|
226
236
|
* Ex: if `openAuthSessionAsync` is invoked on `https://localhost:19006`, then `maybeCompleteAuthSession`
|
|
@@ -257,7 +267,7 @@ export async function openAuthSessionAsync(
|
|
|
257
267
|
throw new UnavailabilityError('WebBrowser', 'openAuthSessionAsync');
|
|
258
268
|
}
|
|
259
269
|
if (['ios', 'web'].includes(Platform.OS)) {
|
|
260
|
-
return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl, options);
|
|
270
|
+
return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl, _processOptions(options));
|
|
261
271
|
}
|
|
262
272
|
return ExponentWebBrowser.openAuthSessionAsync(url, redirectUrl);
|
|
263
273
|
} else {
|
|
@@ -318,6 +328,15 @@ export function maybeCompleteAuthSession(
|
|
|
318
328
|
return { type: 'failed', message: 'Not supported on this platform' };
|
|
319
329
|
}
|
|
320
330
|
|
|
331
|
+
function _processOptions(options: WebBrowserOpenOptions) {
|
|
332
|
+
return {
|
|
333
|
+
...options,
|
|
334
|
+
controlsColor: processColor(options.controlsColor),
|
|
335
|
+
toolbarColor: processColor(options.toolbarColor),
|
|
336
|
+
secondaryToolbarColor: processColor(options.secondaryToolbarColor),
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
321
340
|
/* iOS <= 10 and Android polyfill for SFAuthenticationSession flow */
|
|
322
341
|
|
|
323
342
|
function _authSessionIsNativelySupported(): boolean {
|
package/src/WebBrowser.types.ts
CHANGED
|
@@ -8,7 +8,7 @@ export type WebBrowserWindowFeatures = Record<string, number | boolean | string>
|
|
|
8
8
|
// @needsAudit
|
|
9
9
|
export type WebBrowserOpenOptions = {
|
|
10
10
|
/**
|
|
11
|
-
* Color of the toolbar
|
|
11
|
+
* Color of the toolbar. Supports React Native [color formats](https://reactnative.dev/docs/colors).
|
|
12
12
|
*/
|
|
13
13
|
toolbarColor?: string;
|
|
14
14
|
/**
|
|
@@ -22,7 +22,7 @@ export type WebBrowserOpenOptions = {
|
|
|
22
22
|
*/
|
|
23
23
|
enableBarCollapsing?: boolean;
|
|
24
24
|
/**
|
|
25
|
-
* Color of the secondary toolbar
|
|
25
|
+
* Color of the secondary toolbar. Supports React Native [color formats](https://reactnative.dev/docs/colors).
|
|
26
26
|
* @platform android
|
|
27
27
|
*/
|
|
28
28
|
secondaryToolbarColor?: string;
|
|
@@ -51,7 +51,7 @@ export type WebBrowserOpenOptions = {
|
|
|
51
51
|
*/
|
|
52
52
|
createTask?: boolean;
|
|
53
53
|
/**
|
|
54
|
-
* Tint color for controls in SKSafariViewController
|
|
54
|
+
* Tint color for controls in SKSafariViewController. Supports React Native [color formats](https://reactnative.dev/docs/colors).
|
|
55
55
|
* @platform ios
|
|
56
56
|
*/
|
|
57
57
|
controlsColor?: string;
|