Android WebView has supported core Safe Browsing features since 2017.
Safe Browsing launched in 2005 to protect users across the web from phishing attacks. It has evolved to give users tools to help protect themselves from web-based threats like malware, unwanted software, and social engineering across desktop and mobile platforms. For info on the feature, see https://safebrowsing.google.com/.
WebView’s Safe Browsing implementation is built on top of Chromium’s Safe Browsing interfaces and library. For each navigation in Android apps when Safe Browsing is enabled, since a single page can contain multiple threats WebView gets the most severe threat for the navigation chain and shows an interstitial.
For WebView versions prior to M126, Safe Browsing on WebView uses the “Local Blocklist” or “V4” protocol. URLs are checked for malware, phishing etc against an on-device blocklist that is periodically updated by Google's servers.
From M126 onwards, WebView uses a “Real-Time” or “V5” protocol for Safe Browsing. URLs are checked in real-time against blocklists maintained by our servers. This blog post highlights the motivation behind real-time safe browsing and go/androidSBv5 explains this protocol in detail. Real-time Safe Browsing can be disabled by the user.
Safe Browsing has many components; for brevity, we will only discuss the ones most relevant to WebView. Based on Safe Browsing’s version (v4 or v5) we have different lookup mechanisms to check if the URL is safe, it all starts from BrowserUrlLoaderThrottle::WillStartRequest which creates the Safe Browsing checker to start the check for url, that checker creates the appropriate lookup mechanism based on some conditions, the following diagram shows the flow in a bigger picture:
SafeBrowsingLookupMechanism is the base class and we have three implementations for it:
hash_realtime == V5. This sends a partial hash of the URL to the server through a proxy.url_realtime == Protego. This sends the URL to the server. This is not currently supported in Android WebView.hash_database == V4. This checks against the local blocklist, which is an on-device database of partial URL hashes. If there is a match in the local database, then this connects to the server to request all URL hashes which match this prefix, and then it finally determines if there is a true match or not.It's worth mentioning that SafeBrowsingLookupMechanismRunner controls LookUpMechanism and sets a timeout for the mechanism to run within. The timeout is defined at the top of the class.
When the check is required in the remote DB, it delegates the call to ApiHandlerBridge, which uses JNI to call StartURLCheck on SafeBrowsingApiBridge. ApiBridge uses the SafetyNetApiHandler (Soon to be SafeBrowsingApiHandler) to make the startUriLookup call, the next section talks about WebView specifics.
See the relevant Chromium classes in //components/safe_browsing/.
Refer to https://developers.google.com/safe-browsing/v4/urls-hashing#hash-prefix-computations for an explanation of how the hashing computation and hash prefixes work in v4 of the protocol.
One of the main classes in WebView implementation is AwUrlCheckerDelegateImpl which defines the 4 threat types WebView support in the constructor, it calls WebViewClient#onSafeBrowsingHit to allow the app to respond, also it handles the app’s response to the callback, the default behavior is to show interstitial by calling ui_manager->DisplayBlockingPage. When the callback returns backToSafety() or the user clicks “back to safety” button in the interstitial the class triggers onReceivedError() callback.
WebView has its own allowlisting mechanism which lives in AwSafeBrowsingAllowlistManager, it was implemented to serve a specific API, setSafeBrowsingAllowlist, and that doesn’t have anything to do with the allowlisting in //components (WebView uses both of them but they are unaffiliated).
Any WebView Safe Browsing UI specific logic is being managed by AwSafeBrowsingUIManager, that includes creating the interstitial based on the error.
Depending on which Safe Browsing features you need to test, you may need to build WebView from an upstream (public) or a downstream (internal) build target.
Upstream (public) WebView targets support a limited form of Safe Browsing. WebView only supports blocking hard-coded URLs, but this is sufficient if all you need is to create an interstitial for testing. You can build and install system_webview_apk (see quick start).
The WebView we ship to users is based on downstream (private) build targets. If you need to test the GMS-based implementation which we use to block real malware, you need to build one of the downstream targets. See Google-internal instructions.
If Google Play Services (AKA GMSCore) is uninstalled, disabled, or out-of-date, WebView cannot perform Safe Browsing checks (with the exception of hard-coded URLs). Before trying Safe Browsing locally, make sure this is up-to-date:
$ adb shell am start -a "android.intent.action.VIEW" -d "market://details?id=com.google.android.gms" # Then, manually update GMS in the UI.
If Google Play Services is installed, the user must opt into Google Play Protect's “Verify Apps” setting. This is a single setting, however it can be accessed by your choice of two different routes:
Launch the Play Store app > User icon > Play Protect > Settings (gear icon) > Scan apps with Play Protect, orLaunch the Settings app > Security & Privacy > App Security > Google Play Protect > Gear icon > Scan apps with Play ProtectTo enable real-time Safe Browsing, which is available M126 onwards, ensure that you have opted into it.
Launch Settings > Security & Privacy > More Security & Privacy > Android Safe Browsing > Use live threat protection
If this toggle is off, WebView will still perform Safe Browsing, but will use the “Local Blocklist” (V4) protocol instead of the “Real-time” (V5) protocol.
Safe Browsing is enabled by default, but applications can explicitly disable it with a manifest tag:
<manifest> <application> <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="false" /> ... </application> </manifest>
WebView supports Safe Browsing checks (for testing purposes) on hard-coded WebUI URLs defined in //components/safe_browsing/core/common/web_ui_constants.cc (ex. chrome://safe-browsing/match?type=malware).
These URLs don't show meaningful content, but will trigger an interstitial when trying to navigate to them. WebView relies on these URLs in our CTS tests, so they must never change (but more URLs may be added).
See this page.
Automated tests live here.
You can manually test Safe Browsing with the WebView Shell. Navigate to one of the hard-coded URLs mentioned above.
To test more complex scenarios and WebView's Safe Browsing APIs, please try out the open source WebView demo app.
As Chrome supports more threat types, so can WebView. The steps are:
WebViewClient.java, please consult a WebView team member before this step). The new threat type constant should only be used when the application targets the new Android SDK: use SAFE_BROWSING_THREAT_UNKNOWN for apps with older targetSdkVersions (see http://crbug.com/887186#c15 and http://b/117470538).