blob: 864ee900c92584983565f6fbb8d57531d1dabe16 [file] [log] [blame]
// 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/metrics/field_trial.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/plugins/flash_temporary_permission_tracker.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/content_settings/core/common/pref_names.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_frame_host.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_utils.h"
#include "url/origin.h"
class ChromePluginServiceFilterTest : public ChromeRenderViewHostTestHarness {
public:
ChromePluginServiceFilterTest()
: ChromeRenderViewHostTestHarness(),
filter_(nullptr),
flash_plugin_path_(FILE_PATH_LITERAL("/path/to/flash")) {}
bool IsPluginAvailable(const GURL& plugin_content_url,
const url::Origin& main_frame_origin,
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;
base::PostTaskWithTraitsAndReply(
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(
&ChromePluginServiceFilterTest::IsPluginAvailableOnIOThread,
base::Unretained(this), plugin_content_url, main_frame_origin,
resource_context, plugin_info, &is_available),
run_loop.QuitClosure());
run_loop.Run();
return is_available;
}
protected:
void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp();
// 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& plugin_content_url,
const url::Origin& main_frame_origin,
const void* resource_context,
content::WebPluginInfo plugin_info,
bool* is_available) {
*is_available = filter_->IsPluginAvailable(
web_contents()->GetMainFrame()->GetProcess()->GetID(),
web_contents()->GetMainFrame()->GetRoutingID(), resource_context,
plugin_content_url, main_frame_origin, &plugin_info);
}
ChromePluginServiceFilter* filter_;
base::FilePath flash_plugin_path_;
};
TEST_F(ChromePluginServiceFilterTest, PreferHtmlOverPluginsDefault) {
content::WebPluginInfo flash_plugin(
base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_,
base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin."));
// The default content setting should block Flash.
GURL url("http://www.google.com");
url::Origin main_frame_origin = url::Origin::Create(url);
EXPECT_FALSE(IsPluginAvailable(
url, main_frame_origin, profile()->GetResourceContext(), flash_plugin));
// Block plugins.
HostContentSettingsMap* map =
HostContentSettingsMapFactory::GetForProfile(profile());
map->SetContentSettingDefaultScope(url, url, CONTENT_SETTINGS_TYPE_PLUGINS,
std::string(), CONTENT_SETTING_BLOCK);
EXPECT_FALSE(IsPluginAvailable(
url, main_frame_origin, profile()->GetResourceContext(), flash_plugin));
// Allow plugins.
map->SetContentSettingDefaultScope(url, url, CONTENT_SETTINGS_TYPE_PLUGINS,
std::string(), CONTENT_SETTING_ALLOW);
EXPECT_TRUE(IsPluginAvailable(url, main_frame_origin,
profile()->GetResourceContext(), flash_plugin));
// Detect important content should block plugins without user gesture.
map->SetContentSettingDefaultScope(url, url, CONTENT_SETTINGS_TYPE_PLUGINS,
std::string(),
CONTENT_SETTING_DETECT_IMPORTANT_CONTENT);
EXPECT_FALSE(IsPluginAvailable(
url, main_frame_origin, 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."));
GURL url("http://www.google.com");
url::Origin main_frame_origin = url::Origin::Create(url);
// Allow plugins.
HostContentSettingsMap* map =
HostContentSettingsMapFactory::GetForProfile(profile());
map->SetContentSettingDefaultScope(url, url, CONTENT_SETTINGS_TYPE_PLUGINS,
std::string(), CONTENT_SETTING_ALLOW);
EXPECT_TRUE(IsPluginAvailable(url, main_frame_origin,
profile()->GetResourceContext(), flash_plugin));
// Plugins should be hidden on ASK mode.
map->SetContentSettingDefaultScope(url, url, CONTENT_SETTINGS_TYPE_PLUGINS,
std::string(),
CONTENT_SETTING_DETECT_IMPORTANT_CONTENT);
EXPECT_FALSE(IsPluginAvailable(
url, main_frame_origin, profile()->GetResourceContext(), flash_plugin));
// Block plugins.
map->SetContentSettingDefaultScope(url, url, CONTENT_SETTINGS_TYPE_PLUGINS,
std::string(), CONTENT_SETTING_BLOCK);
EXPECT_FALSE(IsPluginAvailable(
url, main_frame_origin, profile()->GetResourceContext(), flash_plugin));
}
TEST_F(ChromePluginServiceFilterTest,
PreferHtmlOverPluginsIncognitoHasIndependentSetting) {
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."));
GURL url("http://www.google.com");
// Allow plugins for this url in the incognito profile.
HostContentSettingsMap* incognito_map =
HostContentSettingsMapFactory::GetForProfile(incognito);
incognito_map->SetContentSettingDefaultScope(
url, url, CONTENT_SETTINGS_TYPE_PLUGINS, std::string(),
CONTENT_SETTING_ALLOW);
// We pass the availablity check in incognito.
url::Origin main_frame_origin = url::Origin::Create(url);
EXPECT_TRUE(IsPluginAvailable(url, main_frame_origin,
incognito->GetResourceContext(), flash_plugin));
// But the original profile still fails the availability check.
EXPECT_FALSE(IsPluginAvailable(
url, main_frame_origin, profile()->GetResourceContext(), flash_plugin));
}
TEST_F(ChromePluginServiceFilterTest, ManagedSetting) {
content::WebPluginInfo flash_plugin(
base::ASCIIToUTF16(content::kFlashPluginName), flash_plugin_path_,
base::ASCIIToUTF16("1"), base::ASCIIToUTF16("The Flash plugin."));
sync_preferences::TestingPrefServiceSyncable* prefs =
profile()->GetTestingPrefService();
prefs->SetManagedPref(prefs::kManagedDefaultPluginsSetting,
std::make_unique<base::Value>(CONTENT_SETTING_ASK));
GURL url("http://www.google.com");
url::Origin main_frame_origin = url::Origin::Create(url);
NavigateAndCommit(url);
// Flash is normally blocked on the ASK managed policy.
EXPECT_FALSE(IsPluginAvailable(
url, main_frame_origin, profile()->GetResourceContext(), flash_plugin));
// Allow flash temporarily.
FlashTemporaryPermissionTracker::Get(profile())->FlashEnabledForWebContents(
web_contents());
EXPECT_TRUE(IsPluginAvailable(url, main_frame_origin,
profile()->GetResourceContext(), flash_plugin));
}