blob: 256bd8378a156a05db28ecd98e562f82ab8bc8ee [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 "chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h"
#include <string>
#include "base/bind.h"
#include "base/logging.h"
#include "base/time/default_clock.h"
#include "base/values.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/profiles/profile.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/history/core/browser/history_service.h"
#include "components/keyed_service/core/service_access_type.h"
#include "url/gurl.h"
namespace {
// Key into the website setting dict for the smart UI.
const char kInfobarLastShownTimeKey[] = "InfobarLastShownTime";
bool ShouldUseSmartUI() {
#if defined(OS_ANDROID)
return true;
#endif
return false;
}
} // namespace
constexpr base::TimeDelta
SubresourceFilterContentSettingsManager::kDelayBeforeShowingInfobarAgain;
SubresourceFilterContentSettingsManager::
SubresourceFilterContentSettingsManager(Profile* profile)
: history_observer_(this),
settings_map_(HostContentSettingsMapFactory::GetForProfile(profile)),
clock_(std::make_unique<base::DefaultClock>(base::DefaultClock())),
should_use_smart_ui_(ShouldUseSmartUI()) {
DCHECK(profile);
DCHECK(settings_map_);
if (auto* history_service = HistoryServiceFactory::GetForProfile(
profile, ServiceAccessType::EXPLICIT_ACCESS)) {
history_observer_.Add(history_service);
}
}
SubresourceFilterContentSettingsManager::
~SubresourceFilterContentSettingsManager() = default;
ContentSetting SubresourceFilterContentSettingsManager::GetSitePermission(
const GURL& url) const {
return settings_map_->GetContentSetting(
url, GURL(), ContentSettingsType::CONTENT_SETTINGS_TYPE_ADS,
std::string());
}
void SubresourceFilterContentSettingsManager::WhitelistSite(const GURL& url) {
settings_map_->SetContentSettingDefaultScope(
url, GURL(), ContentSettingsType::CONTENT_SETTINGS_TYPE_ADS,
std::string(), CONTENT_SETTING_ALLOW);
}
void SubresourceFilterContentSettingsManager::OnDidShowUI(const GURL& url) {
auto dict = std::make_unique<base::DictionaryValue>();
double now = clock_->Now().ToDoubleT();
dict->SetDouble(kInfobarLastShownTimeKey, now);
SetSiteMetadata(url, std::move(dict));
}
bool SubresourceFilterContentSettingsManager::ShouldShowUIForSite(
const GURL& url) const {
if (!should_use_smart_ui())
return true;
std::unique_ptr<base::DictionaryValue> dict = GetSiteMetadata(url);
if (!dict)
return true;
double last_shown_time_double = 0;
if (dict->GetDouble(kInfobarLastShownTimeKey, &last_shown_time_double)) {
base::Time last_shown = base::Time::FromDoubleT(last_shown_time_double);
if (clock_->Now() - last_shown < kDelayBeforeShowingInfobarAgain)
return false;
}
return true;
}
void SubresourceFilterContentSettingsManager::
ResetSiteMetadataBasedOnActivation(const GURL& url, bool is_activated) {
// Do not reset the metadata if it exists already, it could clobber an
// existing timestamp.
if (!is_activated) {
SetSiteMetadata(url, nullptr);
} else if (!GetSiteMetadata(url)) {
SetSiteMetadata(url, std::make_unique<base::DictionaryValue>());
}
}
std::unique_ptr<base::DictionaryValue>
SubresourceFilterContentSettingsManager::GetSiteMetadata(
const GURL& url) const {
return base::DictionaryValue::From(settings_map_->GetWebsiteSetting(
url, GURL(), CONTENT_SETTINGS_TYPE_ADS_DATA, std::string(), nullptr));
}
void SubresourceFilterContentSettingsManager::SetSiteMetadata(
const GURL& url,
std::unique_ptr<base::DictionaryValue> dict) {
settings_map_->SetWebsiteSettingDefaultScope(
url, GURL(), ContentSettingsType::CONTENT_SETTINGS_TYPE_ADS_DATA,
std::string(), std::move(dict));
}
// When history URLs are deleted, clear the metadata for the smart UI.
void SubresourceFilterContentSettingsManager::OnURLsDeleted(
history::HistoryService* history_service,
const history::DeletionInfo& deletion_info) {
if (deletion_info.IsAllHistory()) {
settings_map_->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_ADS_DATA);
return;
}
for (const auto& entry : deletion_info.deleted_urls_origin_map()) {
const GURL& origin = entry.first;
int remaining_urls = entry.second.first;
if (!origin.is_empty() && remaining_urls == 0)
SetSiteMetadata(origin, nullptr);
}
}