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..2c5be243d23f6b4eba02a5c5d6b007e567c9a8df |
--- /dev/null |
+++ b/chrome/browser/plugins/chrome_plugin_service_filter_unittest.cc |
@@ -0,0 +1,325 @@ |
+// Copyright (c) 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 "chrome/browser/content_settings/host_content_settings_map_factory.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 TestChromePluginServiceFilter : public ChromePluginServiceFilter { |
+ public: |
+ ~TestChromePluginServiceFilter() override {} |
+ |
+ scoped_refptr<PluginPrefs> GetPluginPrefsForProfile( |
+ Profile* profile) override { |
+ // PluginPrefs is null for an incognito testing profile. Return the prefs |
+ // for the original profile as a workaround. |
+ if (profile->IsOffTheRecord()) |
+ return PluginPrefs::GetForTestingProfile(profile->GetOriginalProfile()); |
+ |
+ // PluginPrefs::GetForProfile returns null when called with a testing |
+ // profile. Explicitly call GetForTestingProfile. |
+ return PluginPrefs::GetForTestingProfile(profile); |
+ } |
+}; |
+ |
+class ChromePluginServiceFilterTest : public ChromeRenderViewHostTestHarness { |
+ public: |
+ ChromePluginServiceFilterTest() |
+ : ChromeRenderViewHostTestHarness(), |
+ filter_(nullptr), |
+ flash_plugin_path_(FILE_PATH_LITERAL("/path/to/flash")) { |
+ SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD); |
+ } |
+ |
+ void SetUp() override { |
+ ChromeRenderViewHostTestHarness::SetUp(); |
calamity
2016/09/13 04:14:37
You should call SiteEngagementScore::SetParamValue
dominickn
2016/09/13 04:42:14
Done.
|
+ } |
+ |
+ void InitializeOnUIThread(bool use_incognito_profile) { |
+ PluginFinder::GetInstance(); |
+ filter_.reset(new TestChromePluginServiceFilter()); |
+ Profile* actual_profile = |
+ use_incognito_profile ? profile()->GetOffTheRecordProfile() : profile(); |
+ filter_->RegisterResourceContext(actual_profile, |
+ actual_profile->GetResourceContext()); |
+ } |
+ |
+ void IsPluginAvailable(const GURL& url, |
+ const GURL& policy_url, |
+ const void* resource_context, |
+ const content::WebPluginInfo& plugin_info, |
+ bool expected_result) { |
+ // 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::PostTask( |
+ content::BrowserThread::IO, FROM_HERE, |
+ base::Bind(&ChromePluginServiceFilterTest::IsPluginAvailableOnIOThread, |
+ base::Unretained(this), url, policy_url, resource_context, |
+ plugin_info, expected_result, run_loop.QuitClosure())); |
+ run_loop.Run(); |
+ } |
+ |
+ void IsPluginAvailableOnIOThread(const GURL& url, |
+ const GURL& policy_url, |
+ const void* resource_context, |
+ content::WebPluginInfo plugin_info, |
+ bool expected_result, |
+ const base::Closure& quit_closure) { |
+ EXPECT_EQ( |
+ expected_result, |
+ filter_->IsPluginAvailable( |
+ web_contents()->GetRenderProcessHost()->GetID(), |
+ web_contents()->GetMainFrame()->GetRoutingID(), |
+ resource_context, url, policy_url, &plugin_info)); |
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
+ quit_closure); |
+ } |
+ |
+ protected: |
+ std::unique_ptr<TestChromePluginServiceFilter> filter_; |
+ base::FilePath flash_plugin_path_; |
+}; |
+ |
+TEST_F(ChromePluginServiceFilterTest, FlashAvailableByDefault) { |
+ InitializeOnUIThread(false); |
+ content::WebPluginInfo flash_plugin( |
+ base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_, |
+ base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin.")); |
+ IsPluginAvailable(GURL(), GURL(), profile()->GetResourceContext(), |
+ flash_plugin, true); |
+} |
+ |
+TEST_F(ChromePluginServiceFilterTest, PreferHtmlOverPluginsDefault) { |
+ InitializeOnUIThread(false); |
+ content::WebPluginInfo flash_plugin( |
+ base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_, |
+ base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin.")); |
+ |
+ // Activate PreferHtmlOverPlugins. Must be done inline or else |
+ // variations::GetVariationParams crashes when we check engagement. |
+ 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); |
+ |
+ // The default content setting should block Flash, as there should be 0 |
+ // engagement. |
+ GURL url("http://www.google.com"); |
+ IsPluginAvailable(url, url, profile()->GetResourceContext(), flash_plugin, |
+ false); |
+ |
+ base::FeatureList::ClearInstanceForTesting(); |
+} |
+ |
+TEST_F(ChromePluginServiceFilterTest, PreferHtmlOverPluginsAllowed) { |
+ InitializeOnUIThread(false); |
+ content::WebPluginInfo flash_plugin( |
+ base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_, |
+ base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin.")); |
+ |
+ // Activate PreferHtmlOverPlugins. Must be done inline or else |
+ // variations::GetVariationParams crashes when we check engagement. |
+ 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); |
+ |
+ // Allow plugins by default. |
+ HostContentSettingsMap* map = |
+ HostContentSettingsMapFactory::GetForProfile(profile()); |
+ map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
+ CONTENT_SETTING_ALLOW); |
+ |
+ // This should fall through to the content setting and be allowed. |
+ GURL url("http://www.google.com"); |
+ IsPluginAvailable(url, url, profile()->GetResourceContext(), flash_plugin, |
+ true); |
+ |
+ map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
+ CONTENT_SETTING_DETECT_IMPORTANT_CONTENT); |
+ |
+ // This should be blocked due to 0 engagement and a detect content setting. |
+ IsPluginAvailable(url, url, profile()->GetResourceContext(), flash_plugin, |
+ false); |
+ |
+ // The first engagement event adds +0.5 on top. |
+ SiteEngagementService* service = SiteEngagementService::Get(profile()); |
+ service->AddPoints(url, 0.2); |
+ |
+ // Should still be blocked. |
+ IsPluginAvailable(url, url, profile()->GetResourceContext(), flash_plugin, |
+ false); |
+ |
+ // Reaching 1.0 engagement should allow Flash. |
+ service->AddPoints(url, 0.3); |
+ IsPluginAvailable(url, url, profile()->GetResourceContext(), flash_plugin, |
+ true); |
+ |
+ base::FeatureList::ClearInstanceForTesting(); |
+} |
+ |
+TEST_F(ChromePluginServiceFilterTest, PreferHtmlOverPluginsCustomEngagement) { |
+ InitializeOnUIThread(false); |
+ content::WebPluginInfo flash_plugin( |
+ base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_, |
+ base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin.")); |
+ |
+ // Activate PreferHtmlOverPlugins. Must be done inline or else |
+ // variations::GetVariationParams crashes when we check engagement. |
+ 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 a 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"); |
+ IsPluginAvailable(url, url, profile()->GetResourceContext(), flash_plugin, |
+ false); |
+ |
+ // Should still be blocked until engagement reaches 4. |
+ SiteEngagementService* service = SiteEngagementService::Get(profile()); |
+ service->AddPoints(url, 0.5); |
+ IsPluginAvailable(url, url, profile()->GetResourceContext(), flash_plugin, |
+ false); |
+ |
+ service->AddPoints(url, 1.0); |
+ IsPluginAvailable(url, url, profile()->GetResourceContext(), flash_plugin, |
+ false); |
+ service->AddPoints(url, 1.0); |
+ IsPluginAvailable(url, url, profile()->GetResourceContext(), flash_plugin, |
+ false); |
+ service->AddPoints(url, 1.0); |
+ IsPluginAvailable(url, url, profile()->GetResourceContext(), flash_plugin, |
+ true); |
+ |
+ base::FeatureList::ClearInstanceForTesting(); |
+ variations::testing::ClearAllVariationParams(); |
+} |
+ |
+TEST_F(ChromePluginServiceFilterTest, PreferHtmlOverPluginsIncognito) { |
+ InitializeOnUIThread(true); |
+ content::WebPluginInfo flash_plugin( |
+ base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_, |
+ base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin.")); |
+ |
+ // Activate PreferHtmlOverPlugins. Must be done inline or else |
+ // variations::GetVariationParams crashes when we check engagement. |
+ 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); |
+ |
+ // Block plugins in the incognito profile. |
+ HostContentSettingsMap* map = HostContentSettingsMapFactory::GetForProfile( |
+ profile()->GetOffTheRecordProfile()); |
+ map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, |
+ CONTENT_SETTING_BLOCK); |
+ |
+ // We should fail the availablity check in incognito. |
+ GURL url("http://www.google.com"); |
+ IsPluginAvailable(url, url, |
+ profile()->GetOffTheRecordProfile()->GetResourceContext(), |
+ flash_plugin, false); |
+ |
+ // Add sufficient engagement to allow Flash in the original profile. |
+ SiteEngagementService* service = SiteEngagementService::Get(profile()); |
+ service->AddPoints(url, 1.0); |
+ |
+ // 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). |
+ IsPluginAvailable(url, url, |
+ profile()->GetOffTheRecordProfile()->GetResourceContext(), |
+ flash_plugin, true); |
+ |
+ base::FeatureList::ClearInstanceForTesting(); |
+} |