blob: b25826e5a4be67b4fb3007ab0fd29a85ab5c960a [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <string>
#include <utility>
#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_clock.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/subresource_filter/chrome_subresource_filter_client.h"
#include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h"
#include "chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
#include "components/subresource_filter/core/browser/subresource_filter_constants.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace subresource_filter {
const char kSubresourceFilterActionsHistogram[] = "SubresourceFilter.Actions2";
class SubresourceFilterSettingsBrowserTest
: public SubresourceFilterBrowserTest {
public:
void SetUp() override {
EXPECT_CALL(provider_, IsInitializationComplete(::testing::_))
.WillRepeatedly(::testing::Return(true));
policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
SubresourceFilterBrowserTest::SetUp();
}
void UpdatePolicy(const policy::PolicyMap& policy) {
provider_.UpdateChromePolicy(policy);
base::RunLoop().RunUntilIdle();
}
private:
policy::MockConfigurationPolicyProvider provider_;
};
IN_PROC_BROWSER_TEST_F(SubresourceFilterSettingsBrowserTest,
ContentSettingsWhitelist_DoNotActivate) {
ASSERT_NO_FATAL_FAILURE(
SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
GURL url(GetTestUrl("subresource_filter/frame_with_included_script.html"));
ConfigureAsPhishingURL(url);
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
content::ConsoleObserverDelegate console_observer(web_contents(),
kActivationConsoleMessage);
web_contents()->SetDelegate(&console_observer);
// Simulate an explicity whitelisting via content settings.
HostContentSettingsMap* settings_map =
HostContentSettingsMapFactory::GetForProfile(browser()->profile());
settings_map->SetContentSettingDefaultScope(
url, url, ContentSettingsType::CONTENT_SETTINGS_TYPE_ADS, std::string(),
CONTENT_SETTING_ALLOW);
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
// No message for whitelisted url.
EXPECT_TRUE(console_observer.message().empty());
}
IN_PROC_BROWSER_TEST_F(SubresourceFilterSettingsBrowserTest,
ContentSettingsWhitelistGlobal_DoNotActivate) {
ASSERT_NO_FATAL_FAILURE(
SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
GURL url(GetTestUrl("subresource_filter/frame_with_included_script.html"));
ConfigureAsPhishingURL(url);
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
content::ConsoleObserverDelegate console_observer(web_contents(),
kActivationConsoleMessage);
web_contents()->SetDelegate(&console_observer);
// Simulate globally allowing ads via content settings.
HostContentSettingsMap* settings_map =
HostContentSettingsMapFactory::GetForProfile(browser()->profile());
settings_map->SetDefaultContentSetting(
ContentSettingsType::CONTENT_SETTINGS_TYPE_ADS, CONTENT_SETTING_ALLOW);
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
// No message for loads that are not activated.
EXPECT_TRUE(console_observer.message().empty());
}
IN_PROC_BROWSER_TEST_F(SubresourceFilterSettingsBrowserTest,
DrivenByEnterprisePolicy) {
ASSERT_NO_FATAL_FAILURE(
SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
GURL url(GetTestUrl("subresource_filter/frame_with_included_script.html"));
ConfigureAsPhishingURL(url);
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
content::ConsoleObserverDelegate console_observer(web_contents(),
kActivationConsoleMessage);
web_contents()->SetDelegate(&console_observer);
// Disable Ads blocking via enterprise policy.
policy::PolicyMap policy;
policy.Set(policy::key::kAdsSettingForIntrusiveAdsSites,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_ENTERPRISE_DEFAULT,
std::make_unique<base::Value>(CONTENT_SETTING_ALLOW), nullptr);
UpdatePolicy(policy);
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
// No message for whitelisted url.
EXPECT_TRUE(console_observer.message().empty());
// Since the policy change can take effect without browser restart, verify
// that blocking ads via policy here should start blocking ads.
policy.Set(policy::key::kAdsSettingForIntrusiveAdsSites,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_ENTERPRISE_DEFAULT,
std::make_unique<base::Value>(CONTENT_SETTING_BLOCK), nullptr);
UpdatePolicy(policy);
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
}
IN_PROC_BROWSER_TEST_F(SubresourceFilterSettingsBrowserTest,
ContentSettingsAllowWithNoPageActivation_DoNotActivate) {
ASSERT_NO_FATAL_FAILURE(
SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
GURL url(GetTestUrl("subresource_filter/frame_with_included_script.html"));
// Do not configure as phishing URL.
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
// Simulate allowing the subresource filter via content settings.
HostContentSettingsMap* settings_map =
HostContentSettingsMapFactory::GetForProfile(browser()->profile());
settings_map->SetContentSettingDefaultScope(
url, url, ContentSettingsType::CONTENT_SETTINGS_TYPE_ADS, std::string(),
CONTENT_SETTING_BLOCK);
// Setting the site to "allow" should not activate filtering.
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
}
IN_PROC_BROWSER_TEST_F(SubresourceFilterSettingsBrowserTest,
ContentSettingsWhitelistViaReload_DoNotActivate) {
ASSERT_NO_FATAL_FAILURE(
SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
GURL url(GetTestUrl("subresource_filter/frame_with_included_script.html"));
ConfigureAsPhishingURL(url);
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
// Whitelist via a reload.
content::TestNavigationObserver navigation_observer(web_contents(), 1);
ChromeSubresourceFilterClient::FromWebContents(web_contents())
->OnReloadRequested();
navigation_observer.Wait();
EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
}
IN_PROC_BROWSER_TEST_F(SubresourceFilterSettingsBrowserTest,
ContentSettingsWhitelistViaReload_WhitelistIsByDomain) {
ASSERT_NO_FATAL_FAILURE(
SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
GURL url(GetTestUrl("subresource_filter/frame_with_included_script.html"));
ConfigureAsPhishingURL(url);
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
// Whitelist via a reload.
content::TestNavigationObserver navigation_observer(web_contents(), 1);
ChromeSubresourceFilterClient::FromWebContents(web_contents())
->OnReloadRequested();
navigation_observer.Wait();
EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
// Another navigation to the same domain should be whitelisted too.
ui_test_utils::NavigateToURL(
browser(),
GetTestUrl("subresource_filter/frame_with_included_script.html?query"));
EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
// A cross site blacklisted navigation should stay activated, however.
GURL a_url(embedded_test_server()->GetURL(
"a.com", "/subresource_filter/frame_with_included_script.html"));
ConfigureAsPhishingURL(a_url);
ui_test_utils::NavigateToURL(browser(), a_url);
EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
}
// Test the "smart" UI, aka the logic to hide the UI on subsequent same-domain
// navigations, until a certain time threshold has been reached. This is an
// android-only feature.
IN_PROC_BROWSER_TEST_F(SubresourceFilterSettingsBrowserTest,
DoNotShowUIUntilThresholdReached) {
settings_manager()->set_should_use_smart_ui_for_testing(true);
ASSERT_NO_FATAL_FAILURE(
SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
GURL a_url(embedded_test_server()->GetURL(
"a.com", "/subresource_filter/frame_with_included_script.html"));
GURL b_url(embedded_test_server()->GetURL(
"b.com", "/subresource_filter/frame_with_included_script.html"));
// Test utils only support one blacklisted site at a time.
// TODO(csharrison): Add support for more than one URL.
ConfigureAsPhishingURL(a_url);
ChromeSubresourceFilterClient* client =
ChromeSubresourceFilterClient::FromWebContents(web_contents());
auto test_clock = std::make_unique<base::SimpleTestClock>();
base::SimpleTestClock* raw_clock = test_clock.get();
settings_manager()->set_clock_for_testing(std::move(test_clock));
base::HistogramTester histogram_tester;
// First load should trigger the UI.
ui_test_utils::NavigateToURL(browser(), a_url);
EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
EXPECT_TRUE(client->did_show_ui_for_navigation());
histogram_tester.ExpectBucketCount(kSubresourceFilterActionsHistogram,
SubresourceFilterAction::kUISuppressed, 0);
// Second load should not trigger the UI, but should still filter content.
ui_test_utils::NavigateToURL(browser(), a_url);
EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
EXPECT_EQ(client->did_show_ui_for_navigation(), false);
histogram_tester.ExpectBucketCount(kSubresourceFilterActionsHistogram,
SubresourceFilterAction::kUISuppressed, 1);
ConfigureAsPhishingURL(b_url);
// Load to another domain should trigger the UI.
ui_test_utils::NavigateToURL(browser(), b_url);
EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
EXPECT_TRUE(client->did_show_ui_for_navigation());
ConfigureAsPhishingURL(a_url);
// Fast forward the clock, and a_url should trigger the UI again.
raw_clock->Advance(
SubresourceFilterContentSettingsManager::kDelayBeforeShowingInfobarAgain);
ui_test_utils::NavigateToURL(browser(), a_url);
EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
EXPECT_TRUE(client->did_show_ui_for_navigation());
histogram_tester.ExpectBucketCount(kSubresourceFilterActionsHistogram,
SubresourceFilterAction::kUISuppressed, 1);
}
} // namespace subresource_filter