diff --git a/android/java/org/chromium/chrome/browser/BraveApplicationImplBase.java b/android/java/org/chromium/chrome/browser/BraveApplicationImplBase.java index 2cbc6b896dab..bf26a153520d 100644 --- a/android/java/org/chromium/chrome/browser/BraveApplicationImplBase.java +++ b/android/java/org/chromium/chrome/browser/BraveApplicationImplBase.java @@ -10,9 +10,8 @@ import org.chromium.chrome.browser.base.SplitCompatApplication; import org.chromium.chrome.browser.vpn.utils.BraveVpnProfileUtils; - -// TODO(alexeybarabash): needs to be redone for cr130 -// import org.chromium.components.safe_browsing.BraveSafeBrowsingApiHandler; +import org.chromium.components.safe_browsing.BraveSafeBrowsingApiHandler; +import org.chromium.components.safe_browsing.SafeBrowsingApiBridge; public class BraveApplicationImplBase extends SplitCompatApplication.Impl { @Override @@ -27,9 +26,8 @@ public void alwaysOnTriggered() { } }); // Set a handler for SafeBrowsing. It has to be done only once for a process lifetime. - // TODO(alexeybarabash): needs to be redone for cr130 - // SafeBrowsingApiBridge.setSafetyNetApiHandler( - // BraveSafeBrowsingApiHandler.getInstance()); + SafeBrowsingApiBridge.setSafeBrowsingApiHandler( + BraveSafeBrowsingApiHandler.getInstance()); } } } diff --git a/android/java/org/chromium/chrome/browser/app/BraveActivity.java b/android/java/org/chromium/chrome/browser/app/BraveActivity.java index 60a4db71e0db..73afd9938b2b 100644 --- a/android/java/org/chromium/chrome/browser/app/BraveActivity.java +++ b/android/java/org/chromium/chrome/browser/app/BraveActivity.java @@ -157,6 +157,8 @@ import org.chromium.chrome.browser.rate.BraveRateDialogFragment; import org.chromium.chrome.browser.rate.RateUtils; import org.chromium.chrome.browser.rewards.adaptive_captcha.AdaptiveCaptchaHelper; +import org.chromium.chrome.browser.safe_browsing.SafeBrowsingBridge; +import org.chromium.chrome.browser.safe_browsing.SafeBrowsingState; import org.chromium.chrome.browser.set_default_browser.BraveSetDefaultBrowserUtils; import org.chromium.chrome.browser.set_default_browser.OnBraveSetDefaultBrowserListener; import org.chromium.chrome.browser.settings.BraveNewsPreferencesV2; @@ -203,8 +205,7 @@ import org.chromium.components.browser_ui.settings.SettingsLauncher; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.embedder_support.util.UrlUtilities; -// TODO(alexeybarabash): needs to be redone for cr130 -// import org.chromium.components.safe_browsing.BraveSafeBrowsingApiHandler; +import org.chromium.components.safe_browsing.BraveSafeBrowsingApiHandler; import org.chromium.components.search_engines.TemplateUrl; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.content_public.browser.WebContents; @@ -230,8 +231,7 @@ public abstract class BraveActivity extends ChromeActivity OnBraveSetDefaultBrowserListener, ConnectionErrorHandler, PrefObserver, - // TODO(alexeybarabash): needs to be redone for cr130 - // BraveSafeBrowsingApiHandler.BraveSafeBrowsingApiHandlerDelegate, + BraveSafeBrowsingApiHandler.BraveSafeBrowsingApiHandlerDelegate, BraveNewsConnectionErrorHandler.BraveNewsConnectionErrorHandlerDelegate, MiscAndroidMetricsConnectionErrorHandler .MiscAndroidMetricsConnectionErrorHandlerDelegate { @@ -345,17 +345,15 @@ public void onResumeWithNative() { } } - // TODO(alexeybarabash): needs to be redone for cr130 - // BraveSafeBrowsingApiHandler.getInstance().setDelegate( - // BraveActivityJni.get().getSafeBrowsingApiKey(), this); + BraveSafeBrowsingApiHandler.getInstance() + .setDelegate(BraveActivityJni.get().getSafeBrowsingApiKey(), this); // We can store a state of that flag as a browser has to be restarted // when the flag state is changed in any case mSafeBrowsingFlagEnabled = ChromeFeatureList.isEnabled(BraveFeatureList.BRAVE_ANDROID_SAFE_BROWSING); - // TODO(alexeybarabash): needs to be redone for cr130 - // executeInitSafeBrowsing(0); + executeInitSafeBrowsing(0); if (ENABLE_IN_APP_UPDATE) { if (mAppUpdateManager == null) { @@ -479,8 +477,8 @@ protected void onDestroyInternal() { NotificationPermissionController.detach(mNotificationPermissionController); mNotificationPermissionController = null; } - // TODO(alexeybarabash): needs to be redone for cr130 - // BraveSafeBrowsingApiHandler.getInstance().shutdownSafeBrowsing(); + + BraveSafeBrowsingApiHandler.getInstance().shutdownSafeBrowsing(); if (ENABLE_IN_APP_UPDATE && mAppUpdateManager != null) { mAppUpdateManager.unregisterListener(mInstallStateUpdatedListener); } @@ -973,24 +971,21 @@ public void onPreferenceChange() { maybeSolveAdaptiveCaptcha(); } - // TODO(alexeybarabash): needs to be redone for cr130 - // @Override - // public void turnSafeBrowsingOff() { - // SafeBrowsingBridge safeBrowsingBridge = new SafeBrowsingBridge(getCurrentProfile()); - // safeBrowsingBridge.setSafeBrowsingState(SafeBrowsingState.NO_SAFE_BROWSING); - // } + @Override + public void turnSafeBrowsingOff() { + SafeBrowsingBridge safeBrowsingBridge = new SafeBrowsingBridge(getCurrentProfile()); + safeBrowsingBridge.setSafeBrowsingState(SafeBrowsingState.NO_SAFE_BROWSING); + } - // TODO(alexeybarabash): needs to be redone for cr130 - // @Override - // public boolean isSafeBrowsingEnabled() { - // return mSafeBrowsingFlagEnabled; - // } + @Override + public boolean isSafeBrowsingEnabled() { + return mSafeBrowsingFlagEnabled; + } - // TODO(alexeybarabash): needs to be redone for cr130 - // @Override - // public Activity getActivity() { - // return this; - // } + @Override + public Activity getActivity() { + return this; + } public void maybeSolveAdaptiveCaptcha() { String captchaID = @@ -2394,29 +2389,27 @@ public void addOrEditBookmark(final Tab tabToBookmark) { // We call that method with an interval // BraveSafeBrowsingApiHandler.SAFE_BROWSING_INIT_INTERVAL_MS, // as upstream does, to keep the GmsCore process alive. - - // TODO(alexeybarabash): needs to be redone for cr130 - // private void executeInitSafeBrowsing(long delay) { - // // SafeBrowsingBridge.getSafeBrowsingState() has to be executed on a main thread - // PostTask.postDelayedTask( - // TaskTraits.UI_DEFAULT, - // () -> { - // SafeBrowsingBridge safeBrowsingBridge = - // new SafeBrowsingBridge(getCurrentProfile()); - // if (safeBrowsingBridge.getSafeBrowsingState() - // != SafeBrowsingState.NO_SAFE_BROWSING) { - // // initSafeBrowsing could be executed on a background thread - // PostTask.postTask( - // TaskTraits.USER_VISIBLE_MAY_BLOCK, - // () -> { - // BraveSafeBrowsingApiHandler.getInstance().initSafeBrowsing(); - // }); - // } - // executeInitSafeBrowsing( - // BraveSafeBrowsingApiHandler.SAFE_BROWSING_INIT_INTERVAL_MS); - // }, - // delay); - // } + private void executeInitSafeBrowsing(long delay) { + // SafeBrowsingBridge.getSafeBrowsingState() has to be executed on a main thread + PostTask.postDelayedTask( + TaskTraits.UI_DEFAULT, + () -> { + SafeBrowsingBridge safeBrowsingBridge = + new SafeBrowsingBridge(getCurrentProfile()); + if (safeBrowsingBridge.getSafeBrowsingState() + != SafeBrowsingState.NO_SAFE_BROWSING) { + // initSafeBrowsing could be executed on a background thread + PostTask.postTask( + TaskTraits.USER_VISIBLE_MAY_BLOCK, + () -> { + BraveSafeBrowsingApiHandler.getInstance().initSafeBrowsing(); + }); + } + executeInitSafeBrowsing( + BraveSafeBrowsingApiHandler.SAFE_BROWSING_INIT_INTERVAL_MS); + }, + delay); + } public void updateBottomSheetPosition(int orientation) { if (BottomToolbarConfiguration.isBottomToolbarEnabled()) { diff --git a/build/android/config.gni b/build/android/config.gni index aa7e9a41b353..1303360c1b89 100644 --- a/build/android/config.gni +++ b/build/android/config.gni @@ -39,9 +39,7 @@ brave_chrome_java_deps = [ "//brave/components/browser_ui/site_settings/android:java", "//brave/components/misc_metrics/common:mojom_java", "//brave/components/playlist/common/mojom:mojom_java", - - # TODO(alexeybarabash): needs to be redone for cr130 - #"//brave/components/safe_browsing/android:brave_safe_browsing_java", + "//brave/components/safe_browsing/android:brave_safe_browsing_java", "//brave/components/url_sanitizer/common/mojom:mojom_java", "//brave/components/variations/android:java", "//brave/components/version_info/android:java", diff --git a/components/safe_browsing/android/BUILD.gn b/components/safe_browsing/android/BUILD.gn index 1e64ef83b879..974239fc2599 100644 --- a/components/safe_browsing/android/BUILD.gn +++ b/components/safe_browsing/android/BUILD.gn @@ -14,9 +14,11 @@ android_library("brave_safe_browsing_java") { "//components/safe_browsing/android:safe_browsing_java", "//third_party/android_deps:google_play_services_basement_java", "//third_party/android_deps:google_play_services_tasks_java", + "//third_party/androidx:androidx_annotation_annotation_java", ] - # TODO(alexeybarabash): needs to be redone for cr130 - # https://github.com/brave/brave-browser/issues/41165 - sources = [ "java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingApiHandler.java" ] + sources = [ + "java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingApiHandler.java", + "java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingUtils.java", + ] } diff --git a/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingApiHandler.java b/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingApiHandler.java index ea482cadce01..d341dcd24213 100644 --- a/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingApiHandler.java +++ b/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingApiHandler.java @@ -12,32 +12,37 @@ import com.google.android.gms.common.api.ApiException; import com.google.android.gms.common.api.CommonStatusCodes; import com.google.android.gms.safetynet.SafetyNet; +import com.google.android.gms.safetynet.SafetyNetApi.SafeBrowsingResponse; import com.google.android.gms.safetynet.SafetyNetStatusCodes; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - import org.chromium.base.ContextUtils; import org.chromium.base.Log; +import org.chromium.components.safe_browsing.BraveSafeBrowsingUtils.SafeBrowsingJavaResponseStatus; +import org.chromium.components.safe_browsing.BraveSafeBrowsingUtils.SafeBrowsingJavaThreatType; +import org.chromium.components.safe_browsing.SafeBrowsingApiHandler.LookupResult; /** - * Brave implementation of SafetyNetApiHandler for Safe Browsing + * Brave implementation of SafeBrowsingApiHandler for Safe Browsing Under the bonnet it still uses + * SafetyNet. */ -public class BraveSafeBrowsingApiHandler implements SafetyNetApiHandler { +public class BraveSafeBrowsingApiHandler implements SafeBrowsingApiHandler { public static final long SAFE_BROWSING_INIT_INTERVAL_MS = 30000; private static final long DEFAULT_CHECK_DELTA = 10; - private static final String SAFE_METADATA = "{}"; - private static final String TAG = "BraveSafeBrowsingApiHandler"; + private static final String TAG = "BraveSBApiHandler"; + + // This is for |threatAttributes| argument at |SafeBrowsingApiHandler.Observer.onUrlCheckDone| + // It is used only for UMA Histograms, see ReportSafeBrowsingJavaResponse(); and not returned by + // SafetyNet API. + private static final int[] THREAT_ATTRIBUTES_STUB = new int[0]; - /** - *This is a delegate that is implemented in the object where the handler is created - */ + /** This is a delegate that is implemented in the object where the handler is created */ public interface BraveSafeBrowsingApiHandlerDelegate { default void turnSafeBrowsingOff() {} + default boolean isSafeBrowsingEnabled() { return true; } + Activity getActivity(); } @@ -72,103 +77,140 @@ private void resetDelegate() { } @Override - public boolean init(Observer observer) { + public void setObserver(SafeBrowsingApiHandler.Observer observer) { mObserver = observer; - return true; } @Override - public void startUriLookup(final long callbackId, String uri, int[] threatsOfInterest) { + public void startUriLookup(long callbackId, String uri, int[] threatTypes, int protocol) { if (mBraveSafeBrowsingApiHandlerDelegate == null || !mBraveSafeBrowsingApiHandlerDelegate.isSafeBrowsingEnabled() || !isHttpsOrHttp(uri)) { mObserver.onUrlCheckDone( - callbackId, SafeBrowsingResult.TIMEOUT, "{}", DEFAULT_CHECK_DELTA); + callbackId, + LookupResult.FAILURE_API_CALL_TIMEOUT, + SafeBrowsingJavaThreatType.NO_THREAT, + THREAT_ATTRIBUTES_STUB, + SafeBrowsingJavaResponseStatus.SUCCESS_WITH_REAL_TIME, + DEFAULT_CHECK_DELTA); return; } + mTriesCount++; if (!mInitialized) { initSafeBrowsing(); } SafetyNet.getClient(ContextUtils.getApplicationContext()) - .lookupUri(uri, mApiKey, threatsOfInterest) - .addOnSuccessListener(mBraveSafeBrowsingApiHandlerDelegate.getActivity(), + .lookupUri( + uri, + mApiKey, + BraveSafeBrowsingUtils.safeBrowsingToSafetyNetThreatTypes(threatTypes)) + .addOnSuccessListener( + mBraveSafeBrowsingApiHandlerDelegate.getActivity(), sbResponse -> { mTriesCount = 0; - try { - String metadata = SAFE_METADATA; - if (!sbResponse.getDetectedThreats().isEmpty()) { - JSONArray jsonArray = new JSONArray(); - for (int i = 0; i < sbResponse.getDetectedThreats().size(); - i++) { - JSONObject jsonObj = new JSONObject(); - jsonObj.put("threat_type", - String.valueOf(sbResponse.getDetectedThreats() - .get(i) - .getThreatType())); - jsonArray.put(jsonObj); - } - JSONObject finalObj = new JSONObject(); - finalObj.put("matches", jsonArray); - metadata = finalObj.toString(); + if (sbResponse.getDetectedThreats().isEmpty()) { + mObserver.onUrlCheckDone( + callbackId, + LookupResult.SUCCESS, + SafeBrowsingJavaThreatType.NO_THREAT, + THREAT_ATTRIBUTES_STUB, + SafeBrowsingJavaResponseStatus.SUCCESS_WITH_REAL_TIME, + DEFAULT_CHECK_DELTA); + return; + } else { + warnWhenMoreThanOneThreat(sbResponse); + + // Response only with the first code + mObserver.onUrlCheckDone( + callbackId, + LookupResult.SUCCESS, + BraveSafeBrowsingUtils + .safetyNetToSafeBrowsingJavaThreatType( + sbResponse + .getDetectedThreats() + .get(0) + .getThreatType()), + THREAT_ATTRIBUTES_STUB, + SafeBrowsingJavaResponseStatus.SUCCESS_WITH_REAL_TIME, + DEFAULT_CHECK_DELTA); + return; + } + }) + .addOnFailureListener( + mBraveSafeBrowsingApiHandlerDelegate.getActivity(), + e -> { + // An error occurred while communicating with the service. + if (e instanceof ApiException) { + // An error with the Google Play Services API contains some + // additional details. + ApiException apiException = (ApiException) e; + if (isDebuggable()) { + Log.d( + TAG, + "Error: " + + CommonStatusCodes.getStatusCodeString( + apiException.getStatusCode()) + + ", code: " + + apiException.getStatusCode()); + } + if (apiException.getStatusCode() + == CommonStatusCodes.API_NOT_CONNECTED) { + // That means that device doesn't have Google Play Services API. + // Delegate is used to turn off safe browsing option as every + // request is + // delayed when it's turned on and not working + mBraveSafeBrowsingApiHandlerDelegate.turnSafeBrowsingOff(); } - if (mObserver != null) { - mObserver.onUrlCheckDone(callbackId, SafeBrowsingResult.SUCCESS, - metadata, DEFAULT_CHECK_DELTA); + + // Note: If the status code, apiException.getStatusCode(), + // is SafetyNetStatusCodes.SAFE_BROWSING_API_NOT_INITIALIZED, + // you need to call initSafeBrowsing(). It means either you + // haven't called initSafeBrowsing() before or that it needs + // to be called again due to an internal error. + if (mTriesCount <= 1 + && apiException.getStatusCode() + == SafetyNetStatusCodes + .SAFE_BROWSING_API_NOT_INITIALIZED) { + initSafeBrowsing(); + startUriLookup(callbackId, uri, threatTypes, protocol); + } else { + mObserver.onUrlCheckDone( + callbackId, + LookupResult.FAILURE_API_CALL_TIMEOUT, + SafeBrowsingJavaThreatType.NO_THREAT, + THREAT_ATTRIBUTES_STUB, + SafeBrowsingJavaResponseStatus.SUCCESS_WITH_REAL_TIME, + DEFAULT_CHECK_DELTA); } - } catch (JSONException e) { + } else { + // A different, unknown type of error occurred. + if (isDebuggable()) { + Log.d(TAG, "Error: " + e.getMessage()); + } + mObserver.onUrlCheckDone( + callbackId, + LookupResult.FAILURE_API_CALL_TIMEOUT, + SafeBrowsingJavaThreatType.NO_THREAT, + THREAT_ATTRIBUTES_STUB, + SafeBrowsingJavaResponseStatus.SUCCESS_WITH_REAL_TIME, + DEFAULT_CHECK_DELTA); } - }) - .addOnFailureListener(mBraveSafeBrowsingApiHandlerDelegate.getActivity(), e -> { - // An error occurred while communicating with the service. - if (e instanceof ApiException) { - // An error with the Google Play Services API contains some - // additional details. - ApiException apiException = (ApiException) e; - if (isDebuggable()) { - Log.d(TAG, - "Error: " - + CommonStatusCodes.getStatusCodeString( - apiException.getStatusCode()) - + ", code: " + apiException.getStatusCode()); - } - if (apiException.getStatusCode() == CommonStatusCodes.API_NOT_CONNECTED) { - // That means that device doesn't have Google Play Services API. - // Delegate is used to turn off safe browsing option as every request is - // delayed when it's turned on and not working - mBraveSafeBrowsingApiHandlerDelegate.turnSafeBrowsingOff(); - } - - // Note: If the status code, apiException.getStatusCode(), - // is SafetyNetStatusCodes.SAFE_BROWSING_API_NOT_INITIALIZED, - // you need to call initSafeBrowsing(). It means either you - // haven't called initSafeBrowsing() before or that it needs - // to be called again due to an internal error. - if (mTriesCount <= 1 - && apiException.getStatusCode() - == SafetyNetStatusCodes.SAFE_BROWSING_API_NOT_INITIALIZED) { - initSafeBrowsing(); - startUriLookup(callbackId, uri, threatsOfInterest); - } else { - mObserver.onUrlCheckDone(callbackId, SafeBrowsingResult.TIMEOUT, "{}", - DEFAULT_CHECK_DELTA); - } - } else { - // A different, unknown type of error occurred. - if (isDebuggable()) { - Log.d(TAG, "Error: " + e.getMessage()); - } - mObserver.onUrlCheckDone( - callbackId, SafeBrowsingResult.TIMEOUT, "{}", DEFAULT_CHECK_DELTA); - } - mTriesCount = 0; - }); + mTriesCount = 0; + }); } - @Override - public boolean startAllowlistLookup(final String uri, int threatType) { - return false; + private void warnWhenMoreThanOneThreat(SafeBrowsingResponse sbResponse) { + if (sbResponse.getDetectedThreats().size() != 1) { + Log.d(TAG, "Unexpected threats count: " + sbResponse.getDetectedThreats().size()); + String threats = ""; + for (int i = 0; i < sbResponse.getDetectedThreats().size(); i++) { + threats += sbResponse.getDetectedThreats().get(i).getThreatType(); + threats += " "; + } + Log.d(TAG, "Threats: [" + threats + "]"); + } } public void initSafeBrowsing() { @@ -198,14 +240,4 @@ private boolean isDebuggable() { private boolean isHttpsOrHttp(String uri) { return URLUtil.isHttpsUrl(uri) || URLUtil.isHttpUrl(uri); } - - @Override - public void isVerifyAppsEnabled(long callbackId) { - mObserver.onVerifyAppsEnabledDone(callbackId, VerifyAppsResult.SUCCESS_ENABLED); - } - - @Override - public void enableVerifyApps(long callbackId) { - mObserver.onVerifyAppsEnabledDone(callbackId, VerifyAppsResult.SUCCESS_ENABLED); - } } diff --git a/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingUtils.java b/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingUtils.java new file mode 100644 index 000000000000..e33357d54182 --- /dev/null +++ b/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/BraveSafeBrowsingUtils.java @@ -0,0 +1,142 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package org.chromium.components.safe_browsing; + +import androidx.annotation.IntDef; + +import org.chromium.base.Log; + +import java.util.ArrayList; +import java.util.List; + +// This class contains utils to convert +// threat type enums between SafeBrowsing api and SafetyNet api +// Is from CR129 +// src/components/safe_browsing/android/safe_browsing_api_handler_util.h +// +public class BraveSafeBrowsingUtils { + private static final String TAG = "BraveSBUtils"; + + @IntDef({ + SafetyNetJavaThreatType.UNWANTED_SOFTWARE, + SafetyNetJavaThreatType.POTENTIALLY_HARMFUL_APPLICATION, + SafetyNetJavaThreatType.SOCIAL_ENGINEERING, + SafetyNetJavaThreatType.SUBRESOURCE_FILTER, + SafetyNetJavaThreatType.BILLING, + SafetyNetJavaThreatType.CSD_ALLOWLIST, + SafetyNetJavaThreatType.MAX_VALUE + }) + public @interface SafetyNetJavaThreatType { + int UNWANTED_SOFTWARE = 3; + int POTENTIALLY_HARMFUL_APPLICATION = 4; + int SOCIAL_ENGINEERING = 5; + int SUBRESOURCE_FILTER = 13; + int BILLING = 15; + int CSD_ALLOWLIST = 16; + int MAX_VALUE = 17; + } + + @IntDef({ + SafeBrowsingJavaResponseStatus.SUCCESS_WITH_LOCAL_BLOCKLIST, + SafeBrowsingJavaResponseStatus.SUCCESS_WITH_REAL_TIME, + SafeBrowsingJavaResponseStatus.SUCCESS_FALLBACK_REAL_TIME_TIMEOUT, + SafeBrowsingJavaResponseStatus.SUCCESS_FALLBACK_REAL_TIME_THROTTLED, + SafeBrowsingJavaResponseStatus.FAILURE_NETWORK_UNAVAILABLE, + SafeBrowsingJavaResponseStatus.FAILURE_BLOCK_LIST_UNAVAILABLE, + SafeBrowsingJavaResponseStatus.FAILURE_INVALID_URL + }) + public @interface SafeBrowsingJavaResponseStatus { + int SUCCESS_WITH_LOCAL_BLOCKLIST = 0; + int SUCCESS_WITH_REAL_TIME = 1; + int SUCCESS_FALLBACK_REAL_TIME_TIMEOUT = 2; + int SUCCESS_FALLBACK_REAL_TIME_THROTTLED = 3; + int FAILURE_NETWORK_UNAVAILABLE = 4; + int FAILURE_BLOCK_LIST_UNAVAILABLE = 5; + int FAILURE_INVALID_URL = 6; + }; + + @IntDef({ + SafeBrowsingJavaThreatType.NO_THREAT, + SafeBrowsingJavaThreatType.SOCIAL_ENGINEERING, + SafeBrowsingJavaThreatType.UNWANTED_SOFTWARE, + SafeBrowsingJavaThreatType.POTENTIALLY_HARMFUL_APPLICATION, + SafeBrowsingJavaThreatType.BILLING, + SafeBrowsingJavaThreatType.ABUSIVE_EXPERIENCE_VIOLATION, + SafeBrowsingJavaThreatType.BETTER_ADS_VIOLATION + }) + public @interface SafeBrowsingJavaThreatType { + int NO_THREAT = 0; + int SOCIAL_ENGINEERING = 2; + int UNWANTED_SOFTWARE = 3; + int POTENTIALLY_HARMFUL_APPLICATION = 4; + int BILLING = 15; + int ABUSIVE_EXPERIENCE_VIOLATION = 20; + int BETTER_ADS_VIOLATION = 21; + }; + + private static int safeBrowsingToSafetyNetJavaThreatType(int safeBrowsingThreatType) { + switch (safeBrowsingThreatType) { + case SafeBrowsingJavaThreatType.NO_THREAT: + return 0; + case SafeBrowsingJavaThreatType.SOCIAL_ENGINEERING: + return SafetyNetJavaThreatType.SOCIAL_ENGINEERING; + case SafeBrowsingJavaThreatType.UNWANTED_SOFTWARE: + return SafetyNetJavaThreatType.UNWANTED_SOFTWARE; + case SafeBrowsingJavaThreatType.POTENTIALLY_HARMFUL_APPLICATION: + return SafetyNetJavaThreatType.POTENTIALLY_HARMFUL_APPLICATION; + case SafeBrowsingJavaThreatType.BILLING: + return SafetyNetJavaThreatType.BILLING; + case SafeBrowsingJavaThreatType.ABUSIVE_EXPERIENCE_VIOLATION: + case SafeBrowsingJavaThreatType.BETTER_ADS_VIOLATION: + // See SafeBrowsingJavaToSBThreatType at safe_browsing_api_handler_bridge.cc + return SafetyNetJavaThreatType.SUBRESOURCE_FILTER; + default: + Log.d( + TAG, + "safeBrowsingToSafetyNetJavaThreatType: unexpected safeBrowsingThreatType=" + + safeBrowsingThreatType); + return SafetyNetJavaThreatType.MAX_VALUE; + } + } + + public static int[] safeBrowsingToSafetyNetThreatTypes(int[] safeBrowsingThreatTypes) { + List arrSafetyNetThreatTypes = new ArrayList(); + for (int i = 0; i < safeBrowsingThreatTypes.length; ++i) { + int safetyNetThreatType = + safeBrowsingToSafetyNetJavaThreatType(safeBrowsingThreatTypes[i]); + if (safetyNetThreatType != SafetyNetJavaThreatType.MAX_VALUE) { + arrSafetyNetThreatTypes.add(safetyNetThreatType); + } + } + return arrSafetyNetThreatTypes.stream().mapToInt(i -> i).toArray(); + } + + public static int safetyNetToSafeBrowsingJavaThreatType(int safetyNetThreatType) { + switch (safetyNetThreatType) { + case SafetyNetJavaThreatType.BILLING: + return SafeBrowsingJavaThreatType.BILLING; + case SafetyNetJavaThreatType.SUBRESOURCE_FILTER: + assert false + : "safetyNetToSafeBrowsingJavaThreatType: unexpected SUBRESOURCE_FILTER"; + return SafeBrowsingJavaThreatType.NO_THREAT; + case SafetyNetJavaThreatType.SOCIAL_ENGINEERING: + return SafeBrowsingJavaThreatType.SOCIAL_ENGINEERING; + case SafetyNetJavaThreatType.POTENTIALLY_HARMFUL_APPLICATION: + return SafeBrowsingJavaThreatType.POTENTIALLY_HARMFUL_APPLICATION; + case SafetyNetJavaThreatType.UNWANTED_SOFTWARE: + return SafeBrowsingJavaThreatType.UNWANTED_SOFTWARE; + case SafetyNetJavaThreatType.CSD_ALLOWLIST: + assert false : "safetyNetToSafeBrowsingJavaThreatType: unexpected CSD_ALLOWLIST"; + return SafeBrowsingJavaThreatType.NO_THREAT; + default: + Log.d( + TAG, + "safetyNetToSafeBrowsingJavaThreatType: unexpected safetyNetThreatType=" + + safetyNetThreatType); + return SafeBrowsingJavaThreatType.NO_THREAT; + } + } +}