зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1788225 - Part 1: Implementing CookieBannerDomainPrefService. r=pbz
This patch implements the CookieBannerDomainPrefService which manage the per domain pref setting for cookie banner handling. The service uses the nsIContentPrefService2 to store the per site pref value. Differential Revision: https://phabricator.services.mozilla.com/D157866
This commit is contained in:
Родитель
af57c4fb79
Коммит
0d144b3de3
|
@ -0,0 +1,222 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "CookieBannerDomainPrefService.h"
|
||||||
|
|
||||||
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
|
#include "mozilla/DebugOnly.h"
|
||||||
|
#include "mozilla/Logging.h"
|
||||||
|
#include "mozilla/SpinEventLoopUntil.h"
|
||||||
|
#include "mozilla/StaticPtr.h"
|
||||||
|
|
||||||
|
#include "nsIContentPrefService2.h"
|
||||||
|
#include "nsICookieBannerService.h"
|
||||||
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "nsVariant.h"
|
||||||
|
|
||||||
|
#define COOKIE_BANNER_CONTENT_PREF_NAME u"cookiebanner"_ns
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(CookieBannerDomainPrefService, nsIContentPrefCallback2)
|
||||||
|
|
||||||
|
LazyLogModule gCookieBannerPerSitePrefLog("CookieBannerDomainPref");
|
||||||
|
|
||||||
|
static StaticRefPtr<CookieBannerDomainPrefService>
|
||||||
|
sCookieBannerDomainPrefService;
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
already_AddRefed<CookieBannerDomainPrefService>
|
||||||
|
CookieBannerDomainPrefService::GetOrCreate() {
|
||||||
|
if (!sCookieBannerDomainPrefService) {
|
||||||
|
sCookieBannerDomainPrefService = new CookieBannerDomainPrefService();
|
||||||
|
|
||||||
|
ClearOnShutdown(&sCookieBannerDomainPrefService);
|
||||||
|
}
|
||||||
|
|
||||||
|
return do_AddRef(sCookieBannerDomainPrefService);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CookieBannerDomainPrefService::Init() {
|
||||||
|
// Make sure we won't init again.
|
||||||
|
if (mIsInitialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContentPrefService2> contentPrefService =
|
||||||
|
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
||||||
|
|
||||||
|
if (!contentPrefService) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsInitialized = true;
|
||||||
|
|
||||||
|
// Populate the content pref for cookie banner domain preferences.
|
||||||
|
DebugOnly<nsresult> rv = contentPrefService->GetByName(
|
||||||
|
COOKIE_BANNER_CONTENT_PREF_NAME, nullptr, this);
|
||||||
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||||
|
"Fail to get all content prefs during init.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<nsICookieBannerService::Modes> CookieBannerDomainPrefService::GetPref(
|
||||||
|
const nsACString& aDomain, bool aIsPrivate) {
|
||||||
|
// For private windows, the domain prefs will only be stored in memory.
|
||||||
|
if (aIsPrivate) {
|
||||||
|
return mPrefsPrivate.MaybeGet(aDomain);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We return nothing if the first reading of the content pref is not completed
|
||||||
|
// yet. Note that, we won't be able to get the domain pref for early loads.
|
||||||
|
// But, we think this is acceptable because the cookie banners on the early
|
||||||
|
// load tabs would have interacted before when the user disabled the banner
|
||||||
|
// handling. So, there should be consent cookies in place to prevent banner
|
||||||
|
// showing. In this case, our cookie injection and banner clicking won't do
|
||||||
|
// anything.
|
||||||
|
if (!mIsContentPrefLoaded) {
|
||||||
|
return Nothing();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mPrefs.MaybeGet(aDomain);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult CookieBannerDomainPrefService::SetPref(
|
||||||
|
const nsACString& aDomain, nsICookieBannerService::Modes aMode,
|
||||||
|
bool aIsPrivate) {
|
||||||
|
// For private windows, the domain prefs will only be stored in memory.
|
||||||
|
if (aIsPrivate) {
|
||||||
|
Unused << mPrefsPrivate.InsertOrUpdate(aDomain, aMode);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureInitCompleted();
|
||||||
|
|
||||||
|
// Update the in-memory domain preference map.
|
||||||
|
Unused << mPrefs.InsertOrUpdate(aDomain, aMode);
|
||||||
|
|
||||||
|
// Set the preference to the content pref service.
|
||||||
|
nsCOMPtr<nsIContentPrefService2> contentPrefService =
|
||||||
|
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(contentPrefService, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
RefPtr<nsVariant> variant = new nsVariant();
|
||||||
|
nsresult rv = variant->SetAsUint8(aMode);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// Store the domain preference to the content pref service.
|
||||||
|
rv = contentPrefService->Set(NS_ConvertUTF8toUTF16(aDomain),
|
||||||
|
COOKIE_BANNER_CONTENT_PREF_NAME, variant,
|
||||||
|
nullptr, nullptr);
|
||||||
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||||
|
"Fail to set cookie banner domain pref.");
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult CookieBannerDomainPrefService::RemovePref(const nsACString& aDomain,
|
||||||
|
bool aIsPrivate) {
|
||||||
|
// For private windows, we only need to remove in-memory settings.
|
||||||
|
if (aIsPrivate) {
|
||||||
|
mPrefsPrivate.Remove(aDomain);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureInitCompleted();
|
||||||
|
|
||||||
|
mPrefs.Remove(aDomain);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContentPrefService2> contentPrefService =
|
||||||
|
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(contentPrefService, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
// Remove the domain preference from the content pref service.
|
||||||
|
nsresult rv = contentPrefService->RemoveByDomainAndName(
|
||||||
|
NS_ConvertUTF8toUTF16(aDomain), COOKIE_BANNER_CONTENT_PREF_NAME, nullptr,
|
||||||
|
nullptr);
|
||||||
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||||
|
"Fail to remove cookie banner domain pref.");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult CookieBannerDomainPrefService::RemoveAll(bool aIsPrivate) {
|
||||||
|
// For private windows, we only need to remove in-memory settings.
|
||||||
|
if (aIsPrivate) {
|
||||||
|
mPrefsPrivate.Clear();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureInitCompleted();
|
||||||
|
|
||||||
|
mPrefs.Clear();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContentPrefService2> contentPrefService =
|
||||||
|
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(contentPrefService, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
// Remove all the domain preferences.
|
||||||
|
nsresult rv = contentPrefService->RemoveByName(
|
||||||
|
COOKIE_BANNER_CONTENT_PREF_NAME, nullptr, nullptr);
|
||||||
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||||
|
"Fail to remove all cookie banner domain prefs.");
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CookieBannerDomainPrefService::EnsureInitCompleted() {
|
||||||
|
if (mIsContentPrefLoaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until the service is fully initialized.
|
||||||
|
SpinEventLoopUntil("CookieBannerDomainPrefService::EnsureUpdateComplete"_ns,
|
||||||
|
[&] { return mIsContentPrefLoaded; });
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
CookieBannerDomainPrefService::HandleResult(nsIContentPref* aPref) {
|
||||||
|
NS_ENSURE_ARG_POINTER(aPref);
|
||||||
|
|
||||||
|
nsAutoString domain;
|
||||||
|
nsresult rv = aPref->GetDomain(domain);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIVariant> value;
|
||||||
|
rv = aPref->GetValue(getter_AddRefs(value));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t data;
|
||||||
|
rv = value->GetAsUint8(&data);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
Unused << mPrefs.InsertOrUpdate(NS_ConvertUTF16toUTF8(domain),
|
||||||
|
nsICookieBannerService::Modes(data));
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
CookieBannerDomainPrefService::HandleCompletion(uint16_t aReason) {
|
||||||
|
mIsContentPrefLoaded = true;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
CookieBannerDomainPrefService::HandleError(nsresult error) {
|
||||||
|
// We don't need to do anything here because HandleCompletion is always
|
||||||
|
// called.
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(error))) {
|
||||||
|
MOZ_LOG(gCookieBannerPerSitePrefLog, LogLevel::Warning,
|
||||||
|
("Fail to get content pref during initiation."));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,71 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_CookieBannerDomainPrefService_h__
|
||||||
|
#define mozilla_CookieBannerDomainPrefService_h__
|
||||||
|
|
||||||
|
#include "nsIContentPrefService2.h"
|
||||||
|
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
|
#include "nsStringFwd.h"
|
||||||
|
#include "nsTHashMap.h"
|
||||||
|
|
||||||
|
#include "nsICookieBannerService.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
// The service which maintains the per-domain cookie banner preference. It uses
|
||||||
|
// the content pref to store the per-domain preference for cookie banner
|
||||||
|
// handling. To support the synchronous access, the service caches the
|
||||||
|
// preferences in the memory.
|
||||||
|
class CookieBannerDomainPrefService final : public nsIContentPrefCallback2 {
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSICONTENTPREFCALLBACK2
|
||||||
|
|
||||||
|
static already_AddRefed<CookieBannerDomainPrefService> GetOrCreate();
|
||||||
|
|
||||||
|
// Get the preference for the given domain.
|
||||||
|
Maybe<nsICookieBannerService::Modes> GetPref(const nsACString& aDomain,
|
||||||
|
bool aIsPrivate);
|
||||||
|
|
||||||
|
// Set the preference for the given domain.
|
||||||
|
[[nodiscard]] nsresult SetPref(const nsACString& aDomain,
|
||||||
|
nsICookieBannerService::Modes aMode,
|
||||||
|
bool aIsPrivate);
|
||||||
|
|
||||||
|
// Remove the preference for the given domain.
|
||||||
|
[[nodiscard]] nsresult RemovePref(const nsACString& aDomain, bool aIsPrivate);
|
||||||
|
|
||||||
|
// Remove all site preferences.
|
||||||
|
[[nodiscard]] nsresult RemoveAll(bool aIsPrivate);
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
private:
|
||||||
|
~CookieBannerDomainPrefService() = default;
|
||||||
|
|
||||||
|
CookieBannerDomainPrefService()
|
||||||
|
: mIsInitialized(false), mIsContentPrefLoaded(false) {}
|
||||||
|
|
||||||
|
// Indicates whether the service is initialized.
|
||||||
|
bool mIsInitialized;
|
||||||
|
|
||||||
|
// Indicates whether the first reading of content pref completed.
|
||||||
|
bool mIsContentPrefLoaded;
|
||||||
|
|
||||||
|
// Map of the per site preference keyed by domain.
|
||||||
|
nsTHashMap<nsCStringHashKey, nsICookieBannerService::Modes> mPrefs;
|
||||||
|
|
||||||
|
// Map of the per site preference for private windows keyed by domain.
|
||||||
|
nsTHashMap<nsCStringHashKey, nsICookieBannerService::Modes> mPrefsPrivate;
|
||||||
|
|
||||||
|
// A helper function that will wait until the initialization of the content
|
||||||
|
// pref completed.
|
||||||
|
void EnsureInitCompleted();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_CookieBannerDomainPrefService_h__
|
|
@ -36,6 +36,7 @@ EXPORTS.mozilla += [
|
||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
"CookieBannerDomainPrefService.cpp",
|
||||||
"nsClickRule.cpp",
|
"nsClickRule.cpp",
|
||||||
"nsCookieBannerRule.cpp",
|
"nsCookieBannerRule.cpp",
|
||||||
"nsCookieBannerService.cpp",
|
"nsCookieBannerService.cpp",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче