Chromium Code Reviews| Index: chrome/browser/plugins/chrome_plugin_service_filter_unittest.cc |
| diff --git a/chrome/browser/plugins/chrome_plugin_service_filter_unittest.cc b/chrome/browser/plugins/chrome_plugin_service_filter_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..738aff3d1c4187ddf76acee38256e80970f90c09 |
| --- /dev/null |
| +++ b/chrome/browser/plugins/chrome_plugin_service_filter_unittest.cc |
| @@ -0,0 +1,341 @@ |
| +// Copyright 2016 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 "chrome/browser/plugins/chrome_plugin_service_filter.h" |
| + |
| +#include <map> |
| +#include <utility> |
| + |
| +#include "base/bind.h" |
| +#include "base/feature_list.h" |
| +#include "base/files/file_path.h" |
| +#include "base/memory/ptr_util.h" |
| +#include "base/metrics/field_trial.h" |
| +#include "base/run_loop.h" |
| +#include "base/strings/utf_string_conversions.h" |
| +#include "base/test/scoped_feature_list.h" |
| +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| +#include "chrome/browser/engagement/site_engagement_score.h" |
| +#include "chrome/browser/engagement/site_engagement_service.h" |
| +#include "chrome/browser/plugins/plugin_finder.h" |
| +#include "chrome/browser/plugins/plugin_metadata.h" |
| +#include "chrome/browser/plugins/plugin_prefs.h" |
| +#include "chrome/browser/plugins/plugins_field_trial.h" |
| +#include "chrome/common/chrome_content_client.h" |
| +#include "chrome/common/chrome_features.h" |
| +#include "chrome/test/base/chrome_render_view_host_test_harness.h" |
| +#include "chrome/test/base/testing_profile.h" |
| +#include "components/content_settings/core/browser/host_content_settings_map.h" |
| +#include "components/variations/variations_associated_data.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/plugin_service.h" |
| +#include "content/public/browser/render_process_host.h" |
| +#include "content/public/browser/web_contents.h" |
| +#include "content/public/common/content_constants.h" |
| +#include "content/public/test/test_browser_thread_bundle.h" |
| +#include "content/public/test/test_utils.h" |
| + |
| +namespace { |
| + |
| +const char kTrialName[] = "PreferHtmlOverPlugins"; |
| +const char kGroupName[] = "Group1"; |
| + |
| +} // namespace |
| + |
| +class ChromePluginServiceFilterTest : public ChromeRenderViewHostTestHarness { |
| + public: |
| + ChromePluginServiceFilterTest() |
| + : ChromeRenderViewHostTestHarness(), |
| + filter_(nullptr), |
| + flash_plugin_path_(FILE_PATH_LITERAL("/path/to/flash")) { |
| + SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD); |
|
Bernhard Bauer
2016/09/15 09:05:15
Why do you need a real IO thread?
dominickn
2016/09/15 12:16:00
Can we get away with testing without a real IO thr
Bernhard Bauer
2016/09/15 15:39:54
I think the test would still work if you use the s
dominickn
2016/09/16 00:26:01
I don't think it's appropriate to call IsPluginAva
|
| + } |
| + |
| + bool IsPluginAvailable(const GURL& url, |
| + const GURL& policy_url, |
| + const void* resource_context, |
| + const content::WebPluginInfo& plugin_info) { |
| + bool is_available = false; |
| + |
| + // ChromePluginServiceFilter::IsPluginAvailable always runs on the IO |
| + // thread. Use a RunLoop to ensure this method blocks until it posts back. |
| + base::RunLoop run_loop; |
| + content::BrowserThread::PostTaskAndReply( |
| + content::BrowserThread::IO, FROM_HERE, |
| + base::Bind(&ChromePluginServiceFilterTest::IsPluginAvailableOnIOThread, |
| + base::Unretained(this), url, policy_url, resource_context, |
| + plugin_info, &is_available), |
| + run_loop.QuitClosure()); |
| + run_loop.Run(); |
| + |
| + return is_available; |
| + } |
| + |
| + protected: |
| + void SetUp() override { |
| + ChromeRenderViewHostTestHarness::SetUp(); |
| + SiteEngagementScore::SetParamValuesForTesting(); |
| + // Ensure that the testing profile is registered for creating a PluginPrefs. |
| + PluginPrefs::GetForTestingProfile(profile()); |
| + PluginFinder::GetInstance(); |
| + |
| + filter_ = ChromePluginServiceFilter::GetInstance(); |
| + filter_->RegisterResourceContext(profile(), |
| + profile()->GetResourceContext()); |
| + } |
| + |
| + void IsPluginAvailableOnIOThread(const GURL& url, |
| + const GURL& policy_url, |
| + const void* resource_context, |
| + content::WebPluginInfo plugin_info, |
| + bool* is_available) { |
| + *is_available = filter_->IsPluginAvailable( |
| + web_contents()->GetRenderProcessHost()->GetID(), |
| + web_contents()->GetMainFrame()->GetRoutingID(), resource_context, url, |
| + policy_url, &plugin_info); |
| + } |
| + |
| + ChromePluginServiceFilter* filter_; |
| + base::FilePath flash_plugin_path_; |
| +}; |
| + |
| +TEST_F(ChromePluginServiceFilterTest, FlashAvailableByDefault) { |
| + content::WebPluginInfo flash_plugin( |
| + base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_, |
| + base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin.")); |
| + EXPECT_TRUE(IsPluginAvailable(GURL(), GURL(), profile()->GetResourceContext(), |
| + flash_plugin)); |
| +} |
| + |
| +TEST_F(ChromePluginServiceFilterTest, PreferHtmlOverPluginsDefault) { |
| + content::WebPluginInfo flash_plugin( |
| + base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_, |
| + base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin.")); |
| + |
| + // Activate PreferHtmlOverPlugins. |
| + base::test::ScopedFeatureList feature_list; |
| + feature_list.InitAndEnableFeature(features::kPreferHtmlOverPlugins); |
| + |
| + // The default content setting should block Flash, as there should be 0 |
| + // engagement. |
| + GURL url("http://www.google.com"); |
| + EXPECT_FALSE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + // Block plugins. |
| + HostContentSettingsMap* map = |
| + HostContentSettingsMapFactory::GetForProfile(profile()); |
| + map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_BLOCK); |
| + |
| + EXPECT_FALSE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + // Allow plugins. |
| + map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_ALLOW); |
| + |
| + EXPECT_TRUE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + // Detect important content should block on 0 engagement. |
| + map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_DETECT_IMPORTANT_CONTENT); |
| + |
| + EXPECT_FALSE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| +} |
| + |
| +TEST_F(ChromePluginServiceFilterTest, |
| + PreferHtmlOverPluginsAllowOrBlockOverrides) { |
| + content::WebPluginInfo flash_plugin( |
| + base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_, |
| + base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin.")); |
| + |
| + // Activate PreferHtmlOverPlugins. |
| + base::test::ScopedFeatureList feature_list; |
| + feature_list.InitAndEnableFeature(features::kPreferHtmlOverPlugins); |
| + |
| + // Allow plugins by default. |
| + HostContentSettingsMap* map = |
| + HostContentSettingsMapFactory::GetForProfile(profile()); |
| + map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_ALLOW); |
| + |
| + // This should respect the content setting and be allowed. |
| + GURL url("http://www.google.com"); |
| + EXPECT_TRUE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_DETECT_IMPORTANT_CONTENT); |
| + |
| + // This should be blocked due to 0 engagement and a detect content setting. |
| + EXPECT_FALSE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + SiteEngagementService* service = SiteEngagementService::Get(profile()); |
| + service->ResetScoreForURL(url, 0.5); |
| + |
| + // Should still be blocked. |
| + EXPECT_FALSE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + // Reaching 1.0 engagement should allow Flash. |
| + service->ResetScoreForURL(url, 1.0); |
| + EXPECT_TRUE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + // Blocked content setting should override engagement |
| + map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_BLOCK); |
| + EXPECT_FALSE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| +} |
| + |
| +TEST_F(ChromePluginServiceFilterTest, PreferHtmlOverPluginsCustomEngagement) { |
| + content::WebPluginInfo flash_plugin( |
| + base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_, |
| + base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin.")); |
| + |
| + // Activate PreferHtmlOverPlugins and set a custom variation value in the |
| + // feature. |
| + base::FieldTrialList field_trials_(nullptr); |
| + base::FieldTrial* trial = |
| + base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName); |
| + |
| + base::FeatureList::ClearInstanceForTesting(); |
| + std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); |
| + feature_list->RegisterFieldTrialOverride( |
| + features::kPreferHtmlOverPlugins.name, |
| + base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial); |
| + base::FeatureList::SetInstance(std::move(feature_list)); |
| + EXPECT_EQ( |
| + base::FeatureList::GetFieldTrial(features::kPreferHtmlOverPlugins), |
| + trial); |
| + |
| + // Set the custom engagement threshold for Flash. |
| + std::map<std::string, std::string> params; |
| + params[PluginsFieldTrial::kSiteEngagementThresholdForFlashKey] = "4"; |
| + ASSERT_TRUE( |
| + variations::AssociateVariationParams(kTrialName, kGroupName, params)); |
| + std::map<std::string, std::string> actualParams; |
| + EXPECT_TRUE(variations::GetVariationParamsByFeature( |
| + features::kPreferHtmlOverPlugins, &actualParams)); |
| + EXPECT_EQ(params, actualParams); |
| + |
| + // Set to detect important content by default. |
| + HostContentSettingsMap* map = |
| + HostContentSettingsMapFactory::GetForProfile(profile()); |
| + map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_DETECT_IMPORTANT_CONTENT); |
| + |
| + // This should be blocked due to 0 engagement. |
| + GURL url("http://www.google.com"); |
| + EXPECT_FALSE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + // Should still be blocked until engagement reaches 4. |
| + SiteEngagementService* service = SiteEngagementService::Get(profile()); |
| + service->ResetScoreForURL(url, 0.5); |
| + EXPECT_FALSE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + service->ResetScoreForURL(url, 2.0); |
| + EXPECT_FALSE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + service->ResetScoreForURL(url, 3.0); |
| + EXPECT_FALSE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + service->ResetScoreForURL(url, 4.0); |
| + EXPECT_TRUE(IsPluginAvailable(url, url, profile()->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + base::FeatureList::ClearInstanceForTesting(); |
| + variations::testing::ClearAllVariationParams(); |
| +} |
| + |
| +TEST_F(ChromePluginServiceFilterTest, |
| + PreferHtmlOverPluginsIncognitoBlockToDetect) { |
| + Profile* incognito = profile()->GetOffTheRecordProfile(); |
| + filter_->RegisterResourceContext(incognito, incognito->GetResourceContext()); |
| + |
| + content::WebPluginInfo flash_plugin( |
| + base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_, |
| + base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin.")); |
| + |
| + // Activate PreferHtmlOverPlugins. |
| + base::test::ScopedFeatureList feature_list; |
| + feature_list.InitAndEnableFeature(features::kPreferHtmlOverPlugins); |
| + |
| + // Block plugins in the original profile. This should inherit into incognito. |
| + HostContentSettingsMap* map = |
| + HostContentSettingsMapFactory::GetForProfile(profile()); |
| + map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_BLOCK); |
| + |
| + // We should fail the availablity check in incognito. |
| + GURL url("http://www.google.com"); |
| + EXPECT_FALSE(IsPluginAvailable(url, url, incognito->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + // Add sufficient engagement to allow Flash in the original profile. |
| + SiteEngagementService* service = SiteEngagementService::Get(profile()); |
| + service->ResetScoreForURL(url, 1.0); |
| + |
| + // We should still fail the engagement check due to the block. |
| + EXPECT_FALSE(IsPluginAvailable(url, url, incognito->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + // Change to detect important content in the original profile. |
| + map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_DETECT_IMPORTANT_CONTENT); |
| + |
| + // Ensure we pass the engagement check in the incognito profile (i.e. it falls |
| + // back to checking engagement from the original profile when nothing is found |
| + // in the incognito profile). |
| + EXPECT_TRUE(IsPluginAvailable(url, url, incognito->GetResourceContext(), |
| + flash_plugin)); |
| +} |
| + |
| +TEST_F(ChromePluginServiceFilterTest, |
| + PreferHtmlOverPluginsIncognitoAllowToDetect) { |
| + Profile* incognito = profile()->GetOffTheRecordProfile(); |
| + filter_->RegisterResourceContext(incognito, incognito->GetResourceContext()); |
| + |
| + content::WebPluginInfo flash_plugin( |
| + base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_, |
| + base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin.")); |
| + |
| + // Activate PreferHtmlOverPlugins. |
| + base::test::ScopedFeatureList feature_list; |
| + feature_list.InitAndEnableFeature(features::kPreferHtmlOverPlugins); |
| + |
| + // Allow plugins in the original profile. |
| + HostContentSettingsMap* map = |
| + HostContentSettingsMapFactory::GetForProfile(profile()); |
| + map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_ALLOW); |
| + |
| + // We pass the availablity check in incognito based on the original content |
| + // setting. |
| + GURL url("http://www.google.com"); |
| + EXPECT_TRUE(IsPluginAvailable(url, url, incognito->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_DETECT_IMPORTANT_CONTENT); |
| + |
| + // Now we fail the availability check due to the content setting carrying |
| + // over. |
| + EXPECT_FALSE(IsPluginAvailable(url, url, incognito->GetResourceContext(), |
| + flash_plugin)); |
| + |
| + // Add sufficient engagement to allow Flash in the incognito profile. |
| + SiteEngagementService* service = SiteEngagementService::Get(incognito); |
| + service->ResetScoreForURL(url, 2.0); |
| + |
| + // Ensure we pass the engagement check in the incognito profile. |
| + EXPECT_TRUE(IsPluginAvailable(url, url, incognito->GetResourceContext(), |
| + flash_plugin)); |
| +} |