Commit 3bf60675 authored by Nate Fischer's avatar Nate Fischer Committed by Commit Bot

AW: block billing threats

No change to default behavior, because this logic is behind a flag.

This blocks billing threats in WebView, and adds some tests for this
functionality. This involves:

 * Add necessary resources to WebView's whitelist
 * Test Loud and Quiet interstitials
 * Test we use the correct threat type integer in onSafeBrowsingHit
 * Test that the Feature is disabled on trunk
 * Add hardcoded WebUI URL for billing interstitial (also for Chrome)

R=changwan@chromium.org, vakh@chromium.org

      Feature enabled via commandline flag.
    This is necessary to stay consistent with Chrome.

Bug: 887186
Test: run_webview_instrumentation_test_apk --gtest_filter=SafeBrowsingTest#*Billing*
Test: Manual - load chrome://safe-browsing/match?type=billing with
Binary-Size: Increase is due to added WebView strings for the new interstitials.
Change-Id: I695c39ffdd79ef5e771027953bfffc327fc6864b
Reviewed-on: https://chromium-review.googlesource.com/c/1270476Reviewed-by: default avatarCarlos IL <carlosil@chromium.org>
Reviewed-by: default avatarChangwan Ryu <changwan@chromium.org>
Reviewed-by: default avatarVarun Khaneja <vakh@chromium.org>
Commit-Queue: Nate Fischer <ntfschr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600145}
parent 2399f3f3
......@@ -10,9 +10,11 @@
#include "android_webview/browser/aw_safe_browsing_whitelist_manager.h"
#include "android_webview/browser/net/aw_web_resource_request.h"
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/task/post_task.h"
#include "components/safe_browsing/db/database_manager.h"
#include "components/safe_browsing/db/v4_protocol_manager_util.h"
#include "components/safe_browsing/features.h"
#include "components/security_interstitials/content/unsafe_resource.h"
#include "components/security_interstitials/core/urls.h"
#include "content/public/browser/browser_task_traits.h"
......@@ -32,7 +34,11 @@ AwUrlCheckerDelegateImpl::AwUrlCheckerDelegateImpl(
{safe_browsing::SB_THREAT_TYPE_URL_MALWARE,
safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
safe_browsing::SB_THREAT_TYPE_URL_UNWANTED})),
whitelist_manager_(whitelist_manager) {}
whitelist_manager_(whitelist_manager) {
if (base::FeatureList::IsEnabled(safe_browsing::kBillingInterstitial)) {
threat_types_.insert(safe_browsing::SB_THREAT_TYPE_BILLING);
}
}
AwUrlCheckerDelegateImpl::~AwUrlCheckerDelegateImpl() = default;
......
......@@ -13,18 +13,23 @@ import org.chromium.components.safe_browsing.SBThreatType;
* constants in WebViewClient.
*/
public final class AwSafeBrowsingConversionHelper {
/** The resource was blocked for an unknown reason */
/** The resource was blocked for an unknown reason. */
public static final int SAFE_BROWSING_THREAT_UNKNOWN =
WebViewClient.SAFE_BROWSING_THREAT_UNKNOWN;
/** The resource was blocked because it contains malware */
/** The resource was blocked because it contains malware. */
public static final int SAFE_BROWSING_THREAT_MALWARE =
WebViewClient.SAFE_BROWSING_THREAT_MALWARE;
/** The resource was blocked because it contains deceptive content */
/** The resource was blocked because it contains deceptive content. */
public static final int SAFE_BROWSING_THREAT_PHISHING =
WebViewClient.SAFE_BROWSING_THREAT_PHISHING;
/** The resource was blocked because it contains unwanted software */
/** The resource was blocked because it contains unwanted software. */
public static final int SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE =
WebViewClient.SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE;
/** The resource was blocked because it may trick the user into a billing agreement. */
// TODO(ntfschr): add a new int to the SDK.
public static final int SAFE_BROWSING_THREAT_BILLING =
WebViewClient.SAFE_BROWSING_THREAT_UNKNOWN;
/**
* Converts the threat type value from SafeBrowsing code to the WebViewClient constant.
*/
......@@ -36,6 +41,8 @@ public final class AwSafeBrowsingConversionHelper {
return SAFE_BROWSING_THREAT_PHISHING;
case SBThreatType.URL_UNWANTED:
return SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE;
case SBThreatType.BILLING:
return SAFE_BROWSING_THREAT_BILLING;
default:
return SAFE_BROWSING_THREAT_UNKNOWN;
}
......
......@@ -101,6 +101,7 @@ public class SafeBrowsingTest {
private static final int PHISHING_PAGE_BACKGROUND_COLOR = Color.rgb(0, 0, 255);
private static final int MALWARE_PAGE_BACKGROUND_COLOR = Color.rgb(0, 0, 255);
private static final int UNWANTED_SOFTWARE_PAGE_BACKGROUND_COLOR = Color.rgb(0, 0, 255);
private static final int BILLING_PAGE_BACKGROUND_COLOR = Color.rgb(0, 0, 255);
private static final int IFRAME_EMBEDDER_BACKGROUND_COLOR = Color.rgb(10, 10, 10);
private static final String RESOURCE_PATH = "/android_webview/test/data";
......@@ -114,6 +115,7 @@ public class SafeBrowsingTest {
private static final String MALWARE_HTML_PATH = RESOURCE_PATH + "/malware.html";
private static final String UNWANTED_SOFTWARE_HTML_PATH =
RESOURCE_PATH + "/unwanted_software.html";
private static final String BILLING_HTML_PATH = RESOURCE_PATH + "/billing.html";
// A gray page with an iframe to MALWARE_HTML_PATH
private static final String IFRAME_HTML_PATH = RESOURCE_PATH + "/iframe.html";
......@@ -130,9 +132,12 @@ public class SafeBrowsingTest {
public static class MockSafeBrowsingApiHandler implements SafeBrowsingApiHandler {
private Observer mObserver;
private static final String SAFE_METADATA = "{}";
// These codes are defined in "safebrowsing.proto".
private static final int PHISHING_CODE = 5;
private static final int MALWARE_CODE = 4;
private static final int UNWANTED_SOFTWARE_CODE = 3;
private static final int BILLING_CODE = 15;
// Mock time it takes for a lookup request to complete.
private static final long CHECK_DELTA_US = 10;
......@@ -166,6 +171,9 @@ public class SafeBrowsingTest {
} else if (uri.endsWith(UNWANTED_SOFTWARE_HTML_PATH)
&& Arrays.binarySearch(threatsOfInterest, UNWANTED_SOFTWARE_CODE) >= 0) {
metadata = buildMetadataFromCode(UNWANTED_SOFTWARE_CODE);
} else if (uri.endsWith(BILLING_HTML_PATH)
&& Arrays.binarySearch(threatsOfInterest, BILLING_CODE) >= 0) {
metadata = buildMetadataFromCode(BILLING_CODE);
} else {
metadata = SAFE_METADATA;
}
......@@ -483,6 +491,48 @@ public class SafeBrowsingTest {
// the target page
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add("disable-features=BillingInterstitial")
public void testSafeBrowsingDoesNotBlockBillingPages() throws Throwable {
// TODO(ntfschr): this is a temporary check until we launch support for Billing warnings
// (http://crbug/887186).
loadGreenPage();
final String responseUrl = mTestServer.getURL(BILLING_HTML_PATH);
mActivityTestRule.loadUrlSync(
mAwContents, mContentsClient.getOnPageFinishedHelper(), responseUrl);
assertTargetPageHasLoaded(BILLING_PAGE_BACKGROUND_COLOR);
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add("enable-features=BillingInterstitial")
public void testSafeBrowsingBlocksBillingPages() throws Throwable {
loadGreenPage();
loadPathAndWaitForInterstitial(BILLING_HTML_PATH);
assertGreenPageNotShowing();
assertTargetPageNotShowing(BILLING_PAGE_BACKGROUND_COLOR);
// Assume that we are rendering the interstitial, since we see neither the previous page nor
// the target page
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add("enable-features=BillingInterstitial")
public void testSafeBrowsingOnSafeBrowsingHitBillingCode() throws Throwable {
loadGreenPage();
loadPathAndWaitForInterstitial(BILLING_HTML_PATH);
// Check onSafeBrowsingHit arguments
final String responseUrl = mTestServer.getURL(BILLING_HTML_PATH);
Assert.assertEquals(responseUrl, mContentsClient.getLastRequest().url);
Assert.assertEquals(AwSafeBrowsingConversionHelper.SAFE_BROWSING_THREAT_BILLING,
mContentsClient.getLastThreatType());
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
......@@ -749,6 +799,18 @@ public class SafeBrowsingTest {
assertTargetPageNotShowing(UNWANTED_SOFTWARE_PAGE_BACKGROUND_COLOR);
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add("enable-features=BillingInterstitial")
public void testSafeBrowsingCanShowQuietBillingInterstitial() throws Throwable {
mAwContents.setCanShowBigInterstitial(false);
loadGreenPage();
loadPathAndWaitForInterstitial(BILLING_HTML_PATH);
assertGreenPageNotShowing();
assertTargetPageNotShowing(BILLING_PAGE_BACKGROUND_COLOR);
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
......
<html>
<head>
<style>
div {
background-color: rgb(0,0,255);
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
......@@ -16,6 +16,10 @@ IDS_HARMFUL_V3_PRIMARY_PARAGRAPH
IDS_HARMFUL_V3_EXPLANATION_PARAGRAPH
IDS_HARMFUL_V3_EXPLANATION_PARAGRAPH_SUBRESOURCE
IDS_HARMFUL_V3_PROCEED_PARAGRAPH
IDS_BILLING_HEADING
IDS_BILLING_PRIMARY_PARAGRAPH
IDS_BILLING_PRIMARY_BUTTON
IDS_BILLING_PROCEED_BUTTON
IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE
IDS_SAFE_BROWSING_SCOUT_REPORTING_AGREE
IDS_PHISHING_V4_HEADING
......@@ -28,6 +32,8 @@ IDS_PHISHING_WEBVIEW_HEADING
IDS_PHISHING_WEBVIEW_EXPLANATION_PARAGRAPH
IDS_HARMFUL_WEBVIEW_HEADING
IDS_HARMFUL_WEBVIEW_EXPLANATION_PARAGRAPH
IDS_BILLING_WEBVIEW_HEADING
IDS_BILLING_WEBVIEW_EXPLANATION_PARAGRAPH
IDS_SB_UNDER_CONSTRUCTION
IDS_AUTOFILL_CC_AMEX
IDS_AUTOFILL_CC_AMEX_SHORT
......
......@@ -313,9 +313,13 @@ class TestSafeBrowsingBlockingPage : public SafeBrowsingBlockingPage {
class TestSafeBrowsingBlockingPageFactory
: public SafeBrowsingBlockingPageFactory {
public:
TestSafeBrowsingBlockingPageFactory() { }
TestSafeBrowsingBlockingPageFactory() : always_show_back_to_safety_(true) {}
~TestSafeBrowsingBlockingPageFactory() override {}
void SetAlwaysShowBackToSafety(bool value) {
always_show_back_to_safety_ = value;
}
SafeBrowsingBlockingPage* CreateSafeBrowsingPage(
BaseUIManager* delegate,
WebContents* web_contents,
......@@ -340,13 +344,16 @@ class TestSafeBrowsingBlockingPageFactory
web_contents->GetBrowserContext()->IsOffTheRecord(),
is_unified_consent_given, IsExtendedReportingEnabled(*prefs),
IsExtendedReportingPolicyManaged(*prefs), is_proceed_anyway_disabled,
true, // should_open_links_in_new_tab
false, // check_can_go_back_to_safety
true, // should_open_links_in_new_tab
always_show_back_to_safety_,
"cpn_safe_browsing" /* help_center_article_link */);
return new TestSafeBrowsingBlockingPage(delegate, web_contents,
main_frame_url, unsafe_resources,
display_options);
}
private:
bool always_show_back_to_safety_;
};
// Tests the safe browsing blocking page in a browser.
......@@ -427,6 +434,12 @@ class SafeBrowsingBlockingPageBrowserTest
embedded_test_server()->GetURL(kEmptyPage), browser);
}
// The basic version of this method, which uses an HTTP test URL.
GURL SetupWarningAndNavigateInNewTab(Browser* browser) {
return SetupWarningAndNavigateToURLInNewTab(
embedded_test_server()->GetURL(kEmptyPage), browser);
}
// Navigates to a warning on a valid HTTPS website.
GURL SetupWarningAndNavigateToValidHTTPS() {
EXPECT_TRUE(https_server_.Start());
......@@ -775,6 +788,10 @@ class SafeBrowsingBlockingPageBrowserTest
https_server_.GetURL("/title1.html"));
}
void SetAlwaysShowBackToSafety(bool val) {
blocking_page_factory_.SetAlwaysShowBackToSafety(val);
}
protected:
TestThreatDetailsFactory details_factory_;
......@@ -788,6 +805,17 @@ class SafeBrowsingBlockingPageBrowserTest
EXPECT_TRUE(WaitForReady(browser));
return url;
}
// Adds a safebrowsing result of the current test threat to the fake
// safebrowsing service, navigates to that page, and returns the url.
// The various wrappers supply different URLs.
GURL SetupWarningAndNavigateToURLInNewTab(GURL url, Browser* browser) {
SetURLThreatType(url, testing::get<0>(GetParam()));
ui_test_utils::NavigateToURLWithDisposition(
browser, url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
EXPECT_TRUE(WaitForReady(browser));
return url;
}
base::test::ScopedFeatureList scoped_feature_list_;
TestSafeBrowsingServiceFactory factory_;
......@@ -1149,6 +1177,20 @@ IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, ProceedDisabled) {
browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
}
IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageBrowserTest, NoBackToSafety) {
SetAlwaysShowBackToSafety(false);
SetupWarningAndNavigateInNewTab(browser());
EXPECT_EQ(HIDDEN, GetVisibility("primary-button"));
EXPECT_EQ(HIDDEN, GetVisibility("details"));
EXPECT_EQ(HIDDEN, GetVisibility("proceed-link"));
EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
EXPECT_TRUE(Click("details-button"));
EXPECT_EQ(VISIBLE, GetVisibility("details"));
EXPECT_EQ(VISIBLE, GetVisibility("proceed-link"));
EXPECT_EQ(HIDDEN, GetVisibility("error-code"));
}
// Verifies that the reporting checkbox is hidden when opt-in is
// disabled by policy. However, reports can still be sent if extended
// reporting is enabled (eg: by its own policy).
......
......@@ -331,6 +331,8 @@ SBThreatType SafeBrowsingUrlCheckerImpl::CheckWebUIUrls(const GURL& url) {
return safe_browsing::SB_THREAT_TYPE_URL_PHISHING;
if (url == kChromeUISafeBrowsingMatchUnwantedUrl)
return safe_browsing::SB_THREAT_TYPE_URL_UNWANTED;
if (url == kChromeUISafeBrowsingMatchBillingUrl)
return safe_browsing::SB_THREAT_TYPE_BILLING;
return safe_browsing::SB_THREAT_TYPE_SAFE;
}
......
......@@ -10,6 +10,8 @@ const char kChromeUISafeBrowsingURL[] = "chrome://safe-browsing/";
const char kChromeUISafeBrowsingHost[] = "safe-browsing";
const char kSbUnderConstruction[] =
"The safe browsing page is under construction.";
const char kChromeUISafeBrowsingMatchBillingUrl[] =
"chrome://safe-browsing/match?type=billing";
const char kChromeUISafeBrowsingMatchMalwareUrl[] =
"chrome://safe-browsing/match?type=malware";
const char kChromeUISafeBrowsingMatchPhishingUrl[] =
......
......@@ -10,6 +10,7 @@ namespace safe_browsing {
extern const char kChromeUISafeBrowsingURL[];
extern const char kChromeUISafeBrowsingHost[];
extern const char kSbUnderConstruction[];
extern const char kChromeUISafeBrowsingMatchBillingUrl[];
extern const char kChromeUISafeBrowsingMatchMalwareUrl[];
extern const char kChromeUISafeBrowsingMatchPhishingUrl[];
extern const char kChromeUISafeBrowsingMatchUnwantedUrl[];
......
......@@ -311,7 +311,6 @@ void SafeBrowsingLoudErrorUI::PopulateBillingLoadTimeData(
base::DictionaryValue* load_time_data) {
load_time_data->SetBoolean("phishing", false);
load_time_data->SetBoolean("overridable", true);
load_time_data->SetBoolean("hide_primary_button", false);
load_time_data->SetString("heading",
l10n_util::GetStringUTF16(IDS_BILLING_HEADING));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment