| Index: chrome/browser/permissions/permission_decision_auto_blocker.cc
|
| diff --git a/chrome/browser/permissions/permission_decision_auto_blocker.cc b/chrome/browser/permissions/permission_decision_auto_blocker.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..12e7170e22ef149eafa9af2888c58d500bd6c523
|
| --- /dev/null
|
| +++ b/chrome/browser/permissions/permission_decision_auto_blocker.cc
|
| @@ -0,0 +1,168 @@
|
| +// 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/permissions/permission_decision_auto_blocker.h"
|
| +
|
| +#include <memory>
|
| +
|
| +#include "base/feature_list.h"
|
| +#include "base/logging.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/values.h"
|
| +#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
|
| +#include "chrome/browser/permissions/permission_uma_util.h"
|
| +#include "chrome/browser/permissions/permission_util.h"
|
| +#include "chrome/common/chrome_features.h"
|
| +#include "components/content_settings/core/browser/host_content_settings_map.h"
|
| +#include "components/variations/variations_associated_data.h"
|
| +#include "content/public/browser/permission_type.h"
|
| +#include "url/gurl.h"
|
| +
|
| +namespace {
|
| +
|
| +// The default number of times that users may explicitly dismiss a permission
|
| +// prompt from an origin before it is automatically blocked.
|
| +const int kPromptDismissalsBeforeBlock = 3;
|
| +
|
| +std::unique_ptr<base::DictionaryValue> GetOriginDict(
|
| + HostContentSettingsMap* settings,
|
| + const GURL& origin_url) {
|
| + std::unique_ptr<base::DictionaryValue> dict =
|
| + base::DictionaryValue::From(settings->GetWebsiteSetting(
|
| + origin_url, origin_url,
|
| + CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT, std::string(),
|
| + nullptr));
|
| + if (!dict)
|
| + return base::WrapUnique(new base::DictionaryValue());
|
| +
|
| + return dict;
|
| +}
|
| +
|
| +base::DictionaryValue* GetOrCreatePermissionDict(
|
| + base::DictionaryValue* origin_dict,
|
| + const std::string& permission) {
|
| + base::DictionaryValue* permission_dict = nullptr;
|
| + if (!origin_dict->GetDictionaryWithoutPathExpansion(permission,
|
| + &permission_dict)) {
|
| + permission_dict = new base::DictionaryValue();
|
| + origin_dict->SetWithoutPathExpansion(permission,
|
| + base::WrapUnique(permission_dict));
|
| + }
|
| +
|
| + return permission_dict;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +const char PermissionDecisionAutoBlocker::kPromptDismissCountKey[] =
|
| + "dismiss_count";
|
| +
|
| +// static
|
| +const char PermissionDecisionAutoBlocker::kPromptIgnoreCountKey[] =
|
| + "ignore_count";
|
| +
|
| +// static
|
| +void PermissionDecisionAutoBlocker::RemoveCountsByUrl(
|
| + Profile* profile,
|
| + base::Callback<bool(const GURL& url)> filter) {
|
| + HostContentSettingsMap* map =
|
| + HostContentSettingsMapFactory::GetForProfile(profile);
|
| +
|
| + std::unique_ptr<ContentSettingsForOneType> settings(
|
| + new ContentSettingsForOneType);
|
| + map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT,
|
| + std::string(), settings.get());
|
| +
|
| + for (const auto& site : *settings) {
|
| + GURL origin(site.primary_pattern.ToString());
|
| +
|
| + if (origin.is_valid() && filter.Run(origin)) {
|
| + map->SetWebsiteSettingDefaultScope(
|
| + origin, GURL(), CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT,
|
| + std::string(), nullptr);
|
| + }
|
| + }
|
| +}
|
| +
|
| +PermissionDecisionAutoBlocker::PermissionDecisionAutoBlocker(Profile* profile)
|
| + : profile_(profile),
|
| + prompt_dismissals_before_block_(kPromptDismissalsBeforeBlock) {
|
| + UpdateFromVariations();
|
| +}
|
| +
|
| +int PermissionDecisionAutoBlocker::RecordIgnore(
|
| + const GURL& url,
|
| + content::PermissionType permission) {
|
| + int current_ignore_count =
|
| + RecordActionInWebsiteSettings(url, permission, kPromptIgnoreCountKey);
|
| +
|
| + PermissionUmaUtil::PermissionPromptIgnored(permission, current_ignore_count);
|
| +
|
| + return current_ignore_count;
|
| +}
|
| +
|
| +bool PermissionDecisionAutoBlocker::ShouldChangeDismissalToBlock(
|
| + const GURL& url,
|
| + content::PermissionType permission) {
|
| + int current_dismissal_count =
|
| + RecordActionInWebsiteSettings(url, permission, kPromptDismissCountKey);
|
| +
|
| + PermissionUmaUtil::PermissionPromptDismissed(permission,
|
| + current_dismissal_count);
|
| +
|
| + if (!base::FeatureList::IsEnabled(features::kBlockPromptsIfDismissedOften))
|
| + return false;
|
| +
|
| + return current_dismissal_count >= prompt_dismissals_before_block_;
|
| +}
|
| +
|
| +int PermissionDecisionAutoBlocker::GetActionCountForTest(
|
| + const GURL& url,
|
| + content::PermissionType permission,
|
| + const char* key) {
|
| + HostContentSettingsMap* map =
|
| + HostContentSettingsMapFactory::GetForProfile(profile_);
|
| + std::unique_ptr<base::DictionaryValue> dict = GetOriginDict(map, url);
|
| +
|
| + base::DictionaryValue* permission_dict = GetOrCreatePermissionDict(
|
| + dict.get(), PermissionUtil::GetPermissionString(permission));
|
| +
|
| + int current_count = 0;
|
| + permission_dict->GetInteger(key, ¤t_count);
|
| + return current_count;
|
| +}
|
| +
|
| +int PermissionDecisionAutoBlocker::RecordActionInWebsiteSettings(
|
| + const GURL& url,
|
| + content::PermissionType permission,
|
| + const char* key) {
|
| + HostContentSettingsMap* map =
|
| + HostContentSettingsMapFactory::GetForProfile(profile_);
|
| + std::unique_ptr<base::DictionaryValue> dict = GetOriginDict(map, url);
|
| +
|
| + base::DictionaryValue* permission_dict = GetOrCreatePermissionDict(
|
| + dict.get(), PermissionUtil::GetPermissionString(permission));
|
| +
|
| + int current_count = 0;
|
| + permission_dict->GetInteger(key, ¤t_count);
|
| + permission_dict->SetInteger(key, ++current_count);
|
| +
|
| + map->SetWebsiteSettingDefaultScope(
|
| + url, GURL(), CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT,
|
| + std::string(), std::move(dict));
|
| +
|
| + return current_count;
|
| +}
|
| +
|
| +void PermissionDecisionAutoBlocker::UpdateFromVariations() {
|
| + int prompt_dismissals = -1;
|
| + std::string value = variations::GetVariationParamValueByFeature(
|
| + features::kBlockPromptsIfDismissedOften, kPromptDismissCountKey);
|
| +
|
| + // If converting the value fails, stick with the default value.
|
| + if (base::StringToInt(value, &prompt_dismissals) && prompt_dismissals > 0)
|
| + prompt_dismissals_before_block_ = prompt_dismissals;
|
| +}
|
|
|