@aws-amplify/rtn-web-browser 1.0.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.
Files changed (51) hide show
  1. package/AmplifyRTNWebBrowser.podspec +35 -0
  2. package/LICENSE +201 -0
  3. package/android/build.gradle +84 -0
  4. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  5. package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  6. package/android/gradle.properties +23 -0
  7. package/android/gradlew +234 -0
  8. package/android/gradlew.bat +89 -0
  9. package/android/src/hasPackageName/AndroidManifest.xml +9 -0
  10. package/android/src/main/AndroidManifest.xml +8 -0
  11. package/android/src/main/kotlin/com/amazonaws/amplify/rtnwebbrowser/CustomTabsHelper.kt +54 -0
  12. package/android/src/main/kotlin/com/amazonaws/amplify/rtnwebbrowser/WebBrowserModule.kt +74 -0
  13. package/android/src/main/kotlin/com/amazonaws/amplify/rtnwebbrowser/WebBrowserPackage.kt +22 -0
  14. package/android/src/main/kotlin/com/amazonaws/amplify/rtnwebbrowser/WebBrowserServiceConnection.kt +50 -0
  15. package/ios/AmplifyRTNWebBrowser-Bridging-Header.h +6 -0
  16. package/ios/AmplifyRTNWebBrowser.m +14 -0
  17. package/ios/AmplifyRTNWebBrowser.swift +71 -0
  18. package/ios/AmplifyRTNWebBrowser.xcodeproj/project.pbxproj +170 -0
  19. package/ios/AmplifyRTNWebBrowser.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
  20. package/ios/AmplifyRTNWebBrowser.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  21. package/ios/AmplifyRTNWebBrowser.xcworkspace/contents.xcworkspacedata +7 -0
  22. package/ios/AmplifyRTNWebBrowser.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  23. package/lib/apis/openAuthSessionAsync.d.ts +1 -0
  24. package/lib/apis/openAuthSessionAsync.js +68 -0
  25. package/lib/apis/openAuthSessionAsync.js.map +1 -0
  26. package/lib/index.d.ts +4 -0
  27. package/lib/index.js +13 -0
  28. package/lib/index.js.map +1 -0
  29. package/lib/nativeModule.d.ts +2 -0
  30. package/lib/nativeModule.js +18 -0
  31. package/lib/nativeModule.js.map +1 -0
  32. package/lib/types.d.ts +3 -0
  33. package/lib/types.js +5 -0
  34. package/lib/types.js.map +1 -0
  35. package/lib-esm/apis/openAuthSessionAsync.d.ts +1 -0
  36. package/lib-esm/apis/openAuthSessionAsync.js +64 -0
  37. package/lib-esm/apis/openAuthSessionAsync.js.map +1 -0
  38. package/lib-esm/index.d.ts +4 -0
  39. package/lib-esm/index.js +10 -0
  40. package/lib-esm/index.js.map +1 -0
  41. package/lib-esm/nativeModule.d.ts +2 -0
  42. package/lib-esm/nativeModule.js +15 -0
  43. package/lib-esm/nativeModule.js.map +1 -0
  44. package/lib-esm/types.d.ts +3 -0
  45. package/lib-esm/types.js +4 -0
  46. package/lib-esm/types.js.map +1 -0
  47. package/package.json +53 -0
  48. package/src/apis/openAuthSessionAsync.ts +91 -0
  49. package/src/index.ts +12 -0
  50. package/src/nativeModule.ts +23 -0
  51. package/src/types.ts +10 -0
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ package="com.amazonaws.amplify.rtnwebbrowser">
4
+ <queries>
5
+ <intent>
6
+ <action android:name="android.support.customtabs.action.CustomTabsService" />
7
+ </intent>
8
+ </queries>
9
+ </manifest>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <queries>
4
+ <intent>
5
+ <action android:name="android.support.customtabs.action.CustomTabsService" />
6
+ </intent>
7
+ </queries>
8
+ </manifest>
@@ -0,0 +1,54 @@
1
+ package com.amazonaws.amplify.rtnwebbrowser
2
+
3
+ import android.content.Context
4
+ import android.content.Intent
5
+ import android.content.pm.PackageManager
6
+ import android.net.Uri
7
+ import androidx.browser.customtabs.CustomTabsService
8
+
9
+ private const val DUMMY_URL = "http://www.example.com"
10
+
11
+ internal object CustomTabsHelper {
12
+ private var customTabsPackage: String? = null
13
+
14
+ fun getCustomTabsPackageName(context: Context): String? {
15
+ customTabsPackage?.let { return customTabsPackage }
16
+ val packageManager = context.packageManager
17
+ val activityIntent = Intent(Intent.ACTION_VIEW, Uri.parse(DUMMY_URL))
18
+ // Get default VIEW intent handler
19
+ val defaultViewHandlerPackage = packageManager.resolveActivity(
20
+ activityIntent,
21
+ PackageManager.MATCH_DEFAULT_ONLY
22
+ )?.activityInfo?.packageName ?: ""
23
+
24
+ // Get all apps that can handle VIEW intents
25
+ val resolvedActivityList =
26
+ packageManager.queryIntentActivities(activityIntent, PackageManager.MATCH_ALL)
27
+
28
+ // Get all apps that can handle both VIEW intents and service calls
29
+ val packagesSupportingCustomTabs = ArrayList<String>()
30
+ resolvedActivityList.forEach { resolveInfo ->
31
+ val serviceIntent = Intent()
32
+ .setAction(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION)
33
+ .setPackage(resolveInfo.activityInfo.packageName)
34
+ packageManager.resolveService(serviceIntent, PackageManager.MATCH_ALL)?.let {
35
+ packagesSupportingCustomTabs.add(it.serviceInfo.packageName)
36
+ }
37
+ }
38
+
39
+ customTabsPackage = if (packagesSupportingCustomTabs.isEmpty()) {
40
+ // If no packages support custom tabs, return null
41
+ null
42
+ } else if (defaultViewHandlerPackage.isNotEmpty() && packagesSupportingCustomTabs.contains(
43
+ defaultViewHandlerPackage
44
+ )
45
+ ) {
46
+ // Prefer the default browser if it supports Custom Tabs
47
+ defaultViewHandlerPackage
48
+ } else {
49
+ // Otherwise, pick the next favorite Custom Tabs provider
50
+ packagesSupportingCustomTabs[0]
51
+ }
52
+ return customTabsPackage
53
+ }
54
+ }
@@ -0,0 +1,74 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ package com.amazonaws.amplify.rtnwebbrowser
5
+
6
+ import android.annotation.SuppressLint
7
+ import android.content.Intent
8
+ import android.net.Uri
9
+ import android.util.Patterns
10
+ import androidx.browser.customtabs.CustomTabsClient
11
+ import androidx.browser.customtabs.CustomTabsIntent
12
+ import com.amazonaws.amplify.rtnwebbrowser.CustomTabsHelper.getCustomTabsPackageName
13
+ import com.facebook.react.bridge.LifecycleEventListener
14
+ import com.facebook.react.bridge.Promise
15
+ import com.facebook.react.bridge.ReactApplicationContext
16
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
17
+ import com.facebook.react.bridge.ReactMethod
18
+ import java.lang.Exception
19
+
20
+
21
+ private val TAG = WebBrowserModule::class.java.simpleName
22
+
23
+ class WebBrowserModule(
24
+ reactContext: ReactApplicationContext,
25
+ ) : ReactContextBaseJavaModule(reactContext), LifecycleEventListener {
26
+
27
+ private var connection: WebBrowserServiceConnection? = null
28
+
29
+ init {
30
+ reactContext.addLifecycleEventListener(this)
31
+ getCustomTabsPackageName(reactApplicationContext)?.let {
32
+ connection = WebBrowserServiceConnection(reactApplicationContext)
33
+ CustomTabsClient.bindCustomTabsService(reactApplicationContext, it, connection!!)
34
+ }
35
+ }
36
+
37
+ @ReactMethod
38
+ fun openAuthSessionAsync(uriStr: String, promise: Promise) {
39
+ if (!Patterns.WEB_URL.matcher(uriStr).matches()) {
40
+ promise.reject(Throwable("Provided url is invalid"))
41
+ return
42
+ }
43
+ try {
44
+ getCustomTabsPackageName(reactApplicationContext)?.let {
45
+ val customTabsIntent = CustomTabsIntent.Builder(connection?.getSession()).build()
46
+ customTabsIntent.intent.setPackage(it).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
47
+ customTabsIntent.launchUrl(reactApplicationContext, Uri.parse(uriStr))
48
+ } ?: run {
49
+ promise.reject(Throwable("No eligible browser found on device"))
50
+ }
51
+ } catch (e: Exception) {
52
+ promise.reject(e)
53
+ }
54
+ promise.resolve(null)
55
+ }
56
+
57
+ override fun onHostResume() {
58
+ // noop - only overridden as this class implements LifecycleEventListener
59
+ }
60
+
61
+ override fun onHostPause() {
62
+ // noop - only overridden as this class implements LifecycleEventListener
63
+ }
64
+
65
+ override fun onHostDestroy() {
66
+ connection?.destroy()
67
+ connection = null
68
+ }
69
+
70
+
71
+ override fun getName() = "AmplifyRTNWebBrowser"
72
+
73
+ override fun getConstants(): MutableMap<String, Any> = hashMapOf()
74
+ }
@@ -0,0 +1,22 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ package com.amazonaws.amplify.rtnwebbrowser
5
+
6
+ import android.view.View
7
+ import com.facebook.react.ReactPackage
8
+ import com.facebook.react.bridge.NativeModule
9
+ import com.facebook.react.bridge.ReactApplicationContext
10
+ import com.facebook.react.uimanager.ReactShadowNode
11
+ import com.facebook.react.uimanager.ViewManager
12
+
13
+ class WebBrowserPackage : ReactPackage {
14
+
15
+ override fun createViewManagers(
16
+ reactContext: ReactApplicationContext
17
+ ): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()
18
+
19
+ override fun createNativeModules(
20
+ reactContext: ReactApplicationContext
21
+ ): MutableList<NativeModule> = listOf(WebBrowserModule(reactContext)).toMutableList()
22
+ }
@@ -0,0 +1,50 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ package com.amazonaws.amplify.rtnwebbrowser
5
+
6
+ import android.content.ComponentName
7
+ import android.content.Context
8
+ import androidx.browser.customtabs.CustomTabsClient
9
+ import androidx.browser.customtabs.CustomTabsServiceConnection
10
+ import androidx.browser.customtabs.CustomTabsSession
11
+ import com.amazonaws.amplify.rtnwebbrowser.CustomTabsHelper.getCustomTabsPackageName
12
+
13
+ internal class WebBrowserServiceConnection(
14
+ private val context: Context
15
+ ) : CustomTabsServiceConnection() {
16
+ private var customTabsPackage: String? = getCustomTabsPackageName(context)
17
+ private var session: CustomTabsSession? = null
18
+ private var client: CustomTabsClient? = null
19
+
20
+ init {
21
+ session = client?.newSession(null)
22
+ }
23
+
24
+ fun destroy() {
25
+ if (customTabsPackage != null) {
26
+ context.unbindService(this)
27
+ }
28
+ customTabsPackage = null
29
+ client = null
30
+ session = null
31
+ }
32
+
33
+ fun getSession(): CustomTabsSession? {
34
+ return session
35
+ }
36
+
37
+ override fun onCustomTabsServiceConnected(name: ComponentName, client: CustomTabsClient) {
38
+ if (name.packageName === customTabsPackage) {
39
+ client.warmup(0L)
40
+ session = client.newSession(null)
41
+ this.client = client
42
+ }
43
+ }
44
+
45
+ override fun onServiceDisconnected(name: ComponentName) {
46
+ if (name.packageName === customTabsPackage) {
47
+ destroy()
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,6 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ #import <React/RCTBridgeModule.h>
5
+ #import <React/RCTViewManager.h>
6
+ #import <React/RCTRootView.h>
@@ -0,0 +1,14 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ #import <React/RCTBridgeModule.h>
5
+
6
+ @interface RCT_EXTERN_MODULE(AmplifyRTNWebBrowser, NSObject)
7
+
8
+ RCT_EXTERN_METHOD(openAuthSessionAsync:(NSString*)url
9
+ redirectUrlStr:(NSString*)redirectUrlStr
10
+ prefersEphemeralSession:(BOOL)prefersEphemeralSession
11
+ resolve:(RCTPromiseResolveBlock)resolve
12
+ reject:(RCTPromiseRejectBlock)reject)
13
+
14
+ @end
@@ -0,0 +1,71 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import Foundation
5
+ import AuthenticationServices
6
+
7
+ private class PresentationContextProvider: NSObject, ASWebAuthenticationPresentationContextProviding {
8
+ func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
9
+ return ASPresentationAnchor()
10
+ }
11
+ }
12
+
13
+ @objc(AmplifyRTNWebBrowser)
14
+ class AmplifyRTNWebBrowser: NSObject {
15
+ var webBrowserAuthSession: ASWebAuthenticationSession?
16
+ private let presentationContextProvider = PresentationContextProvider()
17
+
18
+ private func isUrlValid(url: URL) -> Bool {
19
+ let scheme = url.scheme?.lowercased()
20
+ return scheme == "http" || scheme == "https"
21
+ }
22
+
23
+ @objc
24
+ func openAuthSessionAsync(_ urlStr: String,
25
+ redirectUrlStr: String,
26
+ prefersEphemeralSession: Bool,
27
+ resolve: @escaping RCTPromiseResolveBlock,
28
+ reject: @escaping RCTPromiseRejectBlock) {
29
+ guard let url = URL(string: urlStr) else {
30
+ reject("ERROR", "provided url is invalid", nil)
31
+ return
32
+ }
33
+
34
+ guard let redirectUrl = URL(string: redirectUrlStr) else {
35
+ reject("ERROR", "provided redirectUrl is invalid", nil)
36
+ return
37
+ }
38
+
39
+ guard isUrlValid(url: url) else {
40
+ reject("ERROR", "provided url is invalid", nil)
41
+ return
42
+ }
43
+
44
+ let authSession = ASWebAuthenticationSession(
45
+ url: url,
46
+ callbackURLScheme: redirectUrl.scheme,
47
+ completionHandler: { url, error in
48
+ if (error as? ASWebAuthenticationSessionError)?.code == .canceledLogin {
49
+ resolve(nil)
50
+ return
51
+ }
52
+ if error != nil {
53
+ reject("ERROR", "error occurred starting auth session", error)
54
+ return
55
+ }
56
+ resolve(url?.absoluteString)
57
+ })
58
+ webBrowserAuthSession = authSession
59
+ authSession.presentationContextProvider = presentationContextProvider
60
+ authSession.prefersEphemeralWebBrowserSession = prefersEphemeralSession
61
+
62
+ DispatchQueue.main.async {
63
+ authSession.start()
64
+ }
65
+ }
66
+
67
+ @objc
68
+ static func requiresMainQueueSetup() -> Bool {
69
+ return true
70
+ }
71
+ }
@@ -0,0 +1,170 @@
1
+ // !$*UTF8*$!
2
+ {
3
+ archiveVersion = 1;
4
+ classes = {
5
+ };
6
+ objectVersion = 46;
7
+ objects = {
8
+
9
+ /* Begin PBXFileReference section */
10
+ D31047282A81EA8200CD9A8D /* AmplifyRTNWebBrowser-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AmplifyRTNWebBrowser-Bridging-Header.h"; sourceTree = "<group>"; };
11
+ D31047292A81EA8200CD9A8D /* AmplifyRTNWebBrowser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AmplifyRTNWebBrowser.m; sourceTree = "<group>"; };
12
+ D310472D2A81EA8200CD9A8D /* AmplifyRTNWebBrowser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AmplifyRTNWebBrowser.swift; sourceTree = "<group>"; };
13
+ /* End PBXFileReference section */
14
+
15
+ /* Begin PBXGroup section */
16
+ 134814211AA4EA7D00B7C361 /* Products */ = {
17
+ isa = PBXGroup;
18
+ children = (
19
+ );
20
+ name = Products;
21
+ sourceTree = "<group>";
22
+ };
23
+ 58B511D21A9E6C8500147676 = {
24
+ isa = PBXGroup;
25
+ children = (
26
+ D31047282A81EA8200CD9A8D /* AmplifyRTNWebBrowser-Bridging-Header.h */,
27
+ D31047292A81EA8200CD9A8D /* AmplifyRTNWebBrowser.m */,
28
+ D310472D2A81EA8200CD9A8D /* AmplifyRTNWebBrowser.swift */,
29
+ 134814211AA4EA7D00B7C361 /* Products */,
30
+ );
31
+ sourceTree = "<group>";
32
+ };
33
+ /* End PBXGroup section */
34
+
35
+ /* Begin PBXProject section */
36
+ 58B511D31A9E6C8500147676 /* Project object */ = {
37
+ isa = PBXProject;
38
+ attributes = {
39
+ LastUpgradeCheck = 0920;
40
+ ORGANIZATIONNAME = Facebook;
41
+ };
42
+ buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "AmplifyRTNWebBrowser" */;
43
+ compatibilityVersion = "Xcode 3.2";
44
+ developmentRegion = English;
45
+ hasScannedForEncodings = 0;
46
+ knownRegions = (
47
+ English,
48
+ en,
49
+ );
50
+ mainGroup = 58B511D21A9E6C8500147676;
51
+ productRefGroup = 58B511D21A9E6C8500147676;
52
+ projectDirPath = "";
53
+ projectRoot = "";
54
+ targets = (
55
+ );
56
+ };
57
+ /* End PBXProject section */
58
+
59
+ /* Begin XCBuildConfiguration section */
60
+ 58B511ED1A9E6C8500147676 /* Debug */ = {
61
+ isa = XCBuildConfiguration;
62
+ buildSettings = {
63
+ ALWAYS_SEARCH_USER_PATHS = NO;
64
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
65
+ CLANG_CXX_LIBRARY = "libc++";
66
+ CLANG_ENABLE_MODULES = YES;
67
+ CLANG_ENABLE_OBJC_ARC = YES;
68
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
69
+ CLANG_WARN_BOOL_CONVERSION = YES;
70
+ CLANG_WARN_COMMA = YES;
71
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
72
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
73
+ CLANG_WARN_EMPTY_BODY = YES;
74
+ CLANG_WARN_ENUM_CONVERSION = YES;
75
+ CLANG_WARN_INFINITE_RECURSION = YES;
76
+ CLANG_WARN_INT_CONVERSION = YES;
77
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
78
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
79
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
80
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
81
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
82
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
83
+ CLANG_WARN_UNREACHABLE_CODE = YES;
84
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
85
+ COPY_PHASE_STRIP = NO;
86
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
87
+ ENABLE_TESTABILITY = YES;
88
+ "EXCLUDED_ARCHS[sdk=*]" = arm64;
89
+ GCC_C_LANGUAGE_STANDARD = gnu99;
90
+ GCC_DYNAMIC_NO_PIC = NO;
91
+ GCC_NO_COMMON_BLOCKS = YES;
92
+ GCC_OPTIMIZATION_LEVEL = 0;
93
+ GCC_PREPROCESSOR_DEFINITIONS = (
94
+ "DEBUG=1",
95
+ "$(inherited)",
96
+ );
97
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
98
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
99
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
100
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
101
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
102
+ GCC_WARN_UNUSED_FUNCTION = YES;
103
+ GCC_WARN_UNUSED_VARIABLE = YES;
104
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
105
+ MTL_ENABLE_DEBUG_INFO = YES;
106
+ ONLY_ACTIVE_ARCH = YES;
107
+ SDKROOT = iphoneos;
108
+ };
109
+ name = Debug;
110
+ };
111
+ 58B511EE1A9E6C8500147676 /* Release */ = {
112
+ isa = XCBuildConfiguration;
113
+ buildSettings = {
114
+ ALWAYS_SEARCH_USER_PATHS = NO;
115
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
116
+ CLANG_CXX_LIBRARY = "libc++";
117
+ CLANG_ENABLE_MODULES = YES;
118
+ CLANG_ENABLE_OBJC_ARC = YES;
119
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
120
+ CLANG_WARN_BOOL_CONVERSION = YES;
121
+ CLANG_WARN_COMMA = YES;
122
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
123
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
124
+ CLANG_WARN_EMPTY_BODY = YES;
125
+ CLANG_WARN_ENUM_CONVERSION = YES;
126
+ CLANG_WARN_INFINITE_RECURSION = YES;
127
+ CLANG_WARN_INT_CONVERSION = YES;
128
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
129
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
130
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
131
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
132
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
133
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
134
+ CLANG_WARN_UNREACHABLE_CODE = YES;
135
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
136
+ COPY_PHASE_STRIP = YES;
137
+ ENABLE_NS_ASSERTIONS = NO;
138
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
139
+ "EXCLUDED_ARCHS[sdk=*]" = arm64;
140
+ GCC_C_LANGUAGE_STANDARD = gnu99;
141
+ GCC_NO_COMMON_BLOCKS = YES;
142
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
143
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
144
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
145
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
146
+ GCC_WARN_UNUSED_FUNCTION = YES;
147
+ GCC_WARN_UNUSED_VARIABLE = YES;
148
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
149
+ MTL_ENABLE_DEBUG_INFO = NO;
150
+ SDKROOT = iphoneos;
151
+ VALIDATE_PRODUCT = YES;
152
+ };
153
+ name = Release;
154
+ };
155
+ /* End XCBuildConfiguration section */
156
+
157
+ /* Begin XCConfigurationList section */
158
+ 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "AmplifyRTNWebBrowser" */ = {
159
+ isa = XCConfigurationList;
160
+ buildConfigurations = (
161
+ 58B511ED1A9E6C8500147676 /* Debug */,
162
+ 58B511EE1A9E6C8500147676 /* Release */,
163
+ );
164
+ defaultConfigurationIsVisible = 0;
165
+ defaultConfigurationName = Release;
166
+ };
167
+ /* End XCConfigurationList section */
168
+ };
169
+ rootObject = 58B511D31A9E6C8500147676 /* Project object */;
170
+ }
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Workspace
3
+ version = "1.0">
4
+ </Workspace>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>IDEDidComputeMac32BitWarning</key>
6
+ <true/>
7
+ </dict>
8
+ </plist>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Workspace
3
+ version = "1.0">
4
+ <FileRef
5
+ location = "group:AmplifyRTNWebBrowser.xcodeproj">
6
+ </FileRef>
7
+ </Workspace>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>IDEDidComputeMac32BitWarning</key>
6
+ <true/>
7
+ </dict>
8
+ </plist>
@@ -0,0 +1 @@
1
+ export declare const openAuthSessionAsync: (url: string, redirectUrls: string[], prefersEphemeralSession?: boolean) => Promise<string | null | undefined>;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.openAuthSessionAsync = void 0;
6
+ const react_native_1 = require("react-native");
7
+ const nativeModule_1 = require("../nativeModule");
8
+ let appStateListener;
9
+ let redirectListener;
10
+ const openAuthSessionAsync = async (url, redirectUrls, prefersEphemeralSession) => {
11
+ // enforce HTTPS
12
+ const httpsUrl = url.replace('http://', 'https://');
13
+ if (react_native_1.Platform.OS === 'ios') {
14
+ return openAuthSessionIOS(httpsUrl, redirectUrls, prefersEphemeralSession);
15
+ }
16
+ if (react_native_1.Platform.OS === 'android') {
17
+ return openAuthSessionAndroid(httpsUrl, redirectUrls);
18
+ }
19
+ };
20
+ exports.openAuthSessionAsync = openAuthSessionAsync;
21
+ const openAuthSessionIOS = async (url, redirectUrls, prefersEphemeralSession = false) => {
22
+ const redirectUrl = redirectUrls.find(
23
+ // take the first non-web url as the deeplink
24
+ item => !item.startsWith('https://') && !item.startsWith('http://'));
25
+ return nativeModule_1.nativeModule.openAuthSessionAsync(url, redirectUrl, prefersEphemeralSession);
26
+ };
27
+ const openAuthSessionAndroid = async (url, redirectUrls) => {
28
+ try {
29
+ const [redirectUrl] = await Promise.all([
30
+ Promise.race([
31
+ // wait for app to redirect, resulting in a redirectUrl
32
+ getRedirectPromise(redirectUrls),
33
+ // wait for app to return some other way, resulting in null
34
+ getAppStatePromise(),
35
+ ]),
36
+ // open chrome tab
37
+ nativeModule_1.nativeModule.openAuthSessionAsync(url),
38
+ ]);
39
+ return redirectUrl;
40
+ }
41
+ finally {
42
+ appStateListener?.remove();
43
+ redirectListener?.remove();
44
+ appStateListener = undefined;
45
+ redirectListener = undefined;
46
+ }
47
+ };
48
+ const getAppStatePromise = () => new Promise(resolve => {
49
+ appStateListener = react_native_1.AppState.addEventListener('change', nextAppState => {
50
+ // if current state is null, the change is from initialization
51
+ if (react_native_1.AppState.currentState === null) {
52
+ return;
53
+ }
54
+ if (nextAppState === 'active') {
55
+ appStateListener?.remove();
56
+ appStateListener = undefined;
57
+ resolve(null);
58
+ }
59
+ });
60
+ });
61
+ const getRedirectPromise = (redirectUrls) => new Promise(resolve => {
62
+ redirectListener = react_native_1.Linking.addEventListener('url', event => {
63
+ if (redirectUrls.some(url => event.url.startsWith(url))) {
64
+ resolve(event.url);
65
+ }
66
+ });
67
+ });
68
+ //# sourceMappingURL=openAuthSessionAsync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openAuthSessionAsync.js","sourceRoot":"","sources":["../../src/apis/openAuthSessionAsync.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ declare const mergedModule: {
2
+ openAuthSessionAsync: (url: string, redirectUrls: string[], prefersEphemeralSession?: boolean | undefined) => Promise<string | null | undefined>;
3
+ };
4
+ export { mergedModule as AmplifyRTNWebBrowser };
package/lib/index.js ADDED
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.AmplifyRTNWebBrowser = void 0;
6
+ const openAuthSessionAsync_1 = require("./apis/openAuthSessionAsync");
7
+ const nativeModule_1 = require("./nativeModule");
8
+ const mergedModule = {
9
+ ...nativeModule_1.nativeModule,
10
+ openAuthSessionAsync: openAuthSessionAsync_1.openAuthSessionAsync,
11
+ };
12
+ exports.AmplifyRTNWebBrowser = mergedModule;
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,qEAAqE;AACrE,sCAAsC;;;AAEtC,sEAAmE;AACnE,iDAA8C;AAE9C,MAAM,YAAY,GAAG;IACpB,GAAG,2BAAY;IACf,oBAAoB,EAApB,2CAAoB;CACpB,CAAC;AAEuB,4CAAoB"}
@@ -0,0 +1,2 @@
1
+ import { WebBrowserNativeModule } from './types';
2
+ export declare const nativeModule: WebBrowserNativeModule;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.nativeModule = void 0;
6
+ const react_native_1 = require("react-native");
7
+ const LINKING_ERROR = `The package '@aws-amplify/rtn-web-browser' doesn't seem to be linked. Make sure: \n\n` +
8
+ react_native_1.Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
9
+ '- You rebuilt the app after installing the package\n' +
10
+ '- You are not using Expo Go\n';
11
+ exports.nativeModule = react_native_1.NativeModules.AmplifyRTNWebBrowser
12
+ ? react_native_1.NativeModules.AmplifyRTNWebBrowser
13
+ : new Proxy({}, {
14
+ get() {
15
+ throw new Error(LINKING_ERROR);
16
+ },
17
+ });
18
+ //# sourceMappingURL=nativeModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nativeModule.js","sourceRoot":"","sources":["../src/nativeModule.ts"],"names":[],"mappings":";AAAA,qEAAqE;AACrE,sCAAsC;;;AAEtC,+CAAuD;AAGvD,MAAM,aAAa,GAClB,uFAAuF;IACvF,uBAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,gCAAgC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACvE,sDAAsD;IACtD,+BAA+B,CAAC;AAEpB,QAAA,YAAY,GACxB,4BAAa,CAAC,oBAAoB;IACjC,CAAC,CAAC,4BAAa,CAAC,oBAAoB;IACpC,CAAC,CAAC,IAAI,KAAK,CACT,EAAE,EACF;QACC,GAAG;YACF,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;QAChC,CAAC;KACD,CACA,CAAC"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export type WebBrowserNativeModule = {
2
+ openAuthSessionAsync: (url: string, redirectUrl?: string, prefersEphemeralSession?: boolean) => Promise<string | null>;
3
+ };
package/lib/types.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,qEAAqE;AACrE,sCAAsC"}