@@ -17,6 +17,7 @@ import android.webkit.CookieManager
1717import android.webkit.DownloadListener
1818import android.webkit.WebSettings
1919import android.webkit.WebView
20+ import android.widget.Toast
2021import androidx.webkit.WebSettingsCompat
2122import androidx.webkit.WebViewFeature
2223import com.facebook.react.bridge.ReadableArray
@@ -29,6 +30,7 @@ import org.json.JSONObject
2930import java.io.UnsupportedEncodingException
3031import java.net.MalformedURLException
3132import java.net.URL
33+ import java.text.Bidi
3234import java.util.Locale
3335
3436val invalidCharRegex = " [\\\\ /%\" ]" .toRegex()
@@ -83,6 +85,9 @@ class RNCWebViewManagerImpl(private val newArch: Boolean = false) {
8385 settings.allowContentAccess = false
8486 settings.allowFileAccessFromFileURLs = false
8587 settings.allowUniversalAccessFromFileURLs = false
88+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
89+ settings.safeBrowsingEnabled = true
90+ }
8691 settings.mixedContentMode = WebSettings .MIXED_CONTENT_NEVER_ALLOW
8792
8893 // Fixes broken full-screen modals/galleries due to body height being 0.
@@ -93,6 +98,10 @@ class RNCWebViewManagerImpl(private val newArch: Boolean = false) {
9398 if (ReactBuildConfig .DEBUG ) {
9499 WebView .setWebContentsDebuggingEnabled(true )
95100 }
101+ // Remove google autofill for Android > 8
102+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
103+ webView.setImportantForAutofill(View .IMPORTANT_FOR_AUTOFILL_NO );
104+ }
96105 webView.setDownloadListener(DownloadListener { url, userAgent, contentDisposition, mimetype, contentLength ->
97106 webView.setIgnoreErrFailedForThisURL(url)
98107 val module = webView.reactApplicationContext.getNativeModule(RNCWebViewModule ::class .java) ? : return @DownloadListener
@@ -109,42 +118,47 @@ class RNCWebViewManagerImpl(private val newArch: Boolean = false) {
109118
110119 val downloadMessage = " Downloading $fileName "
111120
112- val builder = AlertDialog .Builder (webView.context)
113- builder.setMessage(" Do you want to download \n $fileName ?" )
114- builder.setCancelable(false )
115- builder.setPositiveButton(" Download" ) { _, _ ->
116- // Attempt to add cookie, if it exists
117- var urlObj: URL ? = null
118- try {
119- urlObj = URL (url)
120- val baseUrl = urlObj.protocol + " ://" + urlObj.host
121- val cookie = CookieManager .getInstance().getCookie(baseUrl)
122- request.addRequestHeader(" Cookie" , cookie)
123- } catch (e: MalformedURLException ) {
124- Log .w(TAG , " Error getting cookie for DownloadManager" , e)
125- }
126-
127- // Finish setting up request
128- request.addRequestHeader(" User-Agent" , userAgent)
129- request.setTitle(fileName)
130- request.setDescription(downloadMessage)
131- request.allowScanningByMediaScanner()
132- request.setNotificationVisibility(DownloadManager .Request .VISIBILITY_VISIBLE_NOTIFY_COMPLETED )
133- request.setDestinationInExternalPublicDir(Environment .DIRECTORY_DOWNLOADS , fileName)
134- module.setDownloadRequest(request)
135- if (module.grantFileDownloaderPermissions(
136- getDownloadingMessageOrDefault(),
137- getLackPermissionToDownloadMessageOrDefault()
121+ // Filename validation checking for files that use RTL characters and do not allow those types
122+ if (Bidi (fileName, Bidi .DIRECTION_DEFAULT_LEFT_TO_RIGHT ).isMixed) {
123+ Toast .makeText(webView.context, " Invalid filename or type" , Toast .LENGTH_LONG ).show()
124+ } else {
125+ val builder = AlertDialog .Builder (webView.context)
126+ builder.setMessage(" Do you want to download \n $fileName ?" )
127+ builder.setCancelable(false )
128+ builder.setPositiveButton(" Download" ) { _, _ ->
129+ // Attempt to add cookie, if it exists
130+ var urlObj: URL ? = null
131+ try {
132+ urlObj = URL (url)
133+ val baseUrl = urlObj.protocol + " ://" + urlObj.host
134+ val cookie = CookieManager .getInstance().getCookie(baseUrl)
135+ request.addRequestHeader(" Cookie" , cookie)
136+ } catch (e: MalformedURLException ) {
137+ Log .w(TAG , " Error getting cookie for DownloadManager" , e)
138+ }
139+
140+ // Finish setting up request
141+ request.addRequestHeader(" User-Agent" , userAgent)
142+ request.setTitle(fileName)
143+ request.setDescription(downloadMessage)
144+ request.allowScanningByMediaScanner()
145+ request.setNotificationVisibility(DownloadManager .Request .VISIBILITY_VISIBLE_NOTIFY_COMPLETED )
146+ request.setDestinationInExternalPublicDir(Environment .DIRECTORY_DOWNLOADS , fileName)
147+ module.setDownloadRequest(request)
148+ if (module.grantFileDownloaderPermissions(
149+ getDownloadingMessageOrDefault(),
150+ getLackPermissionToDownloadMessageOrDefault()
138151 )
139- ) {
140- module.downloadFile(
152+ ) {
153+ module.downloadFile(
141154 getDownloadingMessageOrDefault()
142- )
155+ )
156+ }
143157 }
158+ builder.setNegativeButton(" Cancel" ) { _: DialogInterface ? , _: Int -> }
159+ val alertDialog = builder.create()
160+ alertDialog.show()
144161 }
145- builder.setNegativeButton(" Cancel" ) { _: DialogInterface ? , _: Int -> }
146- val alertDialog = builder.create()
147- alertDialog.show()
148162 })
149163 return RNCWebViewWrapper (context, webView)
150164 }
0 commit comments