forked from mirrors/gecko-dev
		
	 437b9b58c0
			
		
	
	
		437b9b58c0
		
	
	
	
	
		
			
			This patch adds a new function setDomainPrefAndPersistInPrivateBrowsing() to nsICookieBannerService. This function allows persisting domain pref in the private browsing mode. Differential Revision: https://phabricator.services.mozilla.com/D164797
		
			
				
	
	
		
			484 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			484 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* 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/RefPtr.h"
 | |
| #include "mozilla/Services.h"
 | |
| #include "mozilla/SpinEventLoopUntil.h"
 | |
| #include "mozilla/StaticPtr.h"
 | |
| 
 | |
| #include "nsIContentPrefService2.h"
 | |
| #include "nsICookieBannerService.h"
 | |
| #include "nsIObserverService.h"
 | |
| #include "nsServiceManagerUtils.h"
 | |
| #include "nsVariant.h"
 | |
| 
 | |
| #define COOKIE_BANNER_CONTENT_PREF_NAME u"cookiebanner"_ns
 | |
| #define COOKIE_BANNER_CONTENT_PREF_NAME_PRIVATE u"cookiebannerprivate"_ns
 | |
| 
 | |
| namespace mozilla {
 | |
| 
 | |
| NS_IMPL_ISUPPORTS(CookieBannerDomainPrefService, nsIAsyncShutdownBlocker,
 | |
|                   nsIObserver)
 | |
| 
 | |
| NS_IMPL_ISUPPORTS(CookieBannerDomainPrefService::DomainPrefData, nsISupports)
 | |
| 
 | |
| LazyLogModule gCookieBannerPerSitePrefLog("CookieBannerDomainPref");
 | |
| 
 | |
| static StaticRefPtr<CookieBannerDomainPrefService>
 | |
|     sCookieBannerDomainPrefService;
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| // A helper function to get the profile-before-change shutdown barrier.
 | |
| 
 | |
| nsCOMPtr<nsIAsyncShutdownClient> GetShutdownBarrier() {
 | |
|   nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdownService();
 | |
|   NS_ENSURE_TRUE(svc, nullptr);
 | |
| 
 | |
|   nsCOMPtr<nsIAsyncShutdownClient> barrier;
 | |
|   nsresult rv = svc->GetProfileBeforeChange(getter_AddRefs(barrier));
 | |
|   NS_ENSURE_SUCCESS(rv, nullptr);
 | |
| 
 | |
|   return barrier;
 | |
| }
 | |
| 
 | |
| }  // anonymous namespace
 | |
| 
 | |
| /* static */
 | |
| already_AddRefed<CookieBannerDomainPrefService>
 | |
| CookieBannerDomainPrefService::GetOrCreate() {
 | |
|   if (!sCookieBannerDomainPrefService) {
 | |
|     sCookieBannerDomainPrefService = new CookieBannerDomainPrefService();
 | |
| 
 | |
|     RunOnShutdown([] {
 | |
|       MOZ_LOG(gCookieBannerPerSitePrefLog, LogLevel::Debug, ("RunOnShutdown."));
 | |
| 
 | |
|       sCookieBannerDomainPrefService->Shutdown();
 | |
| 
 | |
|       sCookieBannerDomainPrefService = nullptr;
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   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;
 | |
|   }
 | |
| 
 | |
|   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
 | |
| 
 | |
|   if (!obs) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Register the observer to watch private browsing session ends. We will clean
 | |
|   // the private domain prefs when this happens.
 | |
|   nsresult rv = obs->AddObserver(this, "last-pb-context-exited", false);
 | |
|   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
 | |
|                        "Fail to add observer for 'last-pb-context-exited'.");
 | |
| 
 | |
|   auto initCallback = MakeRefPtr<InitialLoadContentPrefCallback>(this, false);
 | |
| 
 | |
|   // Populate the content pref for cookie banner domain preferences.
 | |
|   rv = contentPrefService->GetByName(COOKIE_BANNER_CONTENT_PREF_NAME, nullptr,
 | |
|                                      initCallback);
 | |
|   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
 | |
|                        "Fail to get all content prefs during init.");
 | |
| 
 | |
|   auto initPrivateCallback =
 | |
|       MakeRefPtr<InitialLoadContentPrefCallback>(this, true);
 | |
| 
 | |
|   // Populate the content pref for the private browsing.
 | |
|   rv = contentPrefService->GetByName(COOKIE_BANNER_CONTENT_PREF_NAME_PRIVATE,
 | |
|                                      nullptr, initPrivateCallback);
 | |
|   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
 | |
|                        "Fail to get all content prefs during init.");
 | |
| 
 | |
|   rv = AddShutdownBlocker();
 | |
|   NS_ENSURE_SUCCESS_VOID(rv);
 | |
| 
 | |
|   mIsInitialized = true;
 | |
| }
 | |
| 
 | |
| void CookieBannerDomainPrefService::Shutdown() {
 | |
|   // Bail out early if the service never gets initialized.
 | |
|   if (!mIsInitialized) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
 | |
| 
 | |
|   if (!obs) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   DebugOnly<nsresult> rv = obs->RemoveObserver(this, "last-pb-context-exited");
 | |
|   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
 | |
|                        "Fail to remove observer for 'last-pb-context-exited'.");
 | |
| }
 | |
| 
 | |
| Maybe<nsICookieBannerService::Modes> CookieBannerDomainPrefService::GetPref(
 | |
|     const nsACString& aDomain, bool aIsPrivate) {
 | |
|   bool isContentPrefLoaded =
 | |
|       aIsPrivate ? mIsPrivateContentPrefLoaded : mIsContentPrefLoaded;
 | |
| 
 | |
|   // 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 (!isContentPrefLoaded) {
 | |
|     return Nothing();
 | |
|   }
 | |
| 
 | |
|   Maybe<RefPtr<DomainPrefData>> data =
 | |
|       aIsPrivate ? mPrefsPrivate.MaybeGet(aDomain) : mPrefs.MaybeGet(aDomain);
 | |
| 
 | |
|   if (!data) {
 | |
|     return Nothing();
 | |
|   }
 | |
| 
 | |
|   return Some(data.ref()->mMode);
 | |
| }
 | |
| 
 | |
| nsresult CookieBannerDomainPrefService::SetPref(
 | |
|     const nsACString& aDomain, nsICookieBannerService::Modes aMode,
 | |
|     bool aIsPrivate, bool aPersistInPrivateBrowsing) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   // Don't do anything if we are shutting down.
 | |
|   if (NS_WARN_IF(mIsShuttingDown)) {
 | |
|     MOZ_LOG(gCookieBannerPerSitePrefLog, LogLevel::Warning,
 | |
|             ("Attempt to set a domain pref while shutting down."));
 | |
|     return NS_OK;
 | |
|   }
 | |
| 
 | |
|   EnsureInitCompleted(aIsPrivate);
 | |
| 
 | |
|   // Create the domain pref data. The data is always persistent for normal
 | |
|   // windows. For private windows, the data is only persistent if requested.
 | |
|   auto domainPrefData = MakeRefPtr<DomainPrefData>(
 | |
|       aMode, aIsPrivate ? aPersistInPrivateBrowsing : true);
 | |
|   bool wasPersistentInPrivate = false;
 | |
| 
 | |
|   // Update the in-memory domain preference map.
 | |
|   if (aIsPrivate) {
 | |
|     Maybe<RefPtr<DomainPrefData>> data = mPrefsPrivate.MaybeGet(aDomain);
 | |
| 
 | |
|     wasPersistentInPrivate = data ? data.ref()->mIsPersistent : false;
 | |
|     Unused << mPrefsPrivate.InsertOrUpdate(aDomain, domainPrefData);
 | |
|   } else {
 | |
|     Unused << mPrefs.InsertOrUpdate(aDomain, domainPrefData);
 | |
|   }
 | |
| 
 | |
|   // For private windows, the domain prefs will only be stored in memory.
 | |
|   // Unless, this function is instructed to persist setting for private
 | |
|   // browsing. To make the disk state consistent with the memory state, we need
 | |
|   // to clear the domain pref in the disk when we no longer need to persist the
 | |
|   // domain pref for the domain in PBM.
 | |
|   if (!aPersistInPrivateBrowsing && aIsPrivate) {
 | |
|     // Clear the domain pref in disk if it was persistent.
 | |
|     if (wasPersistentInPrivate) {
 | |
|       return RemoveContentPrefForDomain(aDomain, true);
 | |
|     }
 | |
|     return NS_OK;
 | |
|   }
 | |
| 
 | |
|   // 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);
 | |
| 
 | |
|   auto callback = MakeRefPtr<WriteContentPrefCallback>(this);
 | |
|   mWritingCount++;
 | |
| 
 | |
|   // Store the domain preference to the content pref service.
 | |
|   rv = contentPrefService->Set(NS_ConvertUTF8toUTF16(aDomain),
 | |
|                                aIsPrivate
 | |
|                                    ? COOKIE_BANNER_CONTENT_PREF_NAME_PRIVATE
 | |
|                                    : COOKIE_BANNER_CONTENT_PREF_NAME,
 | |
|                                variant, nullptr, callback);
 | |
|   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
 | |
|                        "Fail to set cookie banner domain pref.");
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| nsresult CookieBannerDomainPrefService::RemovePref(const nsACString& aDomain,
 | |
|                                                    bool aIsPrivate) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   // Don't do anything if we are shutting down.
 | |
|   if (NS_WARN_IF(mIsShuttingDown)) {
 | |
|     MOZ_LOG(gCookieBannerPerSitePrefLog, LogLevel::Warning,
 | |
|             ("Attempt to remove a domain pref while shutting down."));
 | |
|     return NS_OK;
 | |
|   }
 | |
| 
 | |
|   EnsureInitCompleted(aIsPrivate);
 | |
| 
 | |
|   // Clear in-memory domain pref.
 | |
|   if (aIsPrivate) {
 | |
|     mPrefsPrivate.Remove(aDomain);
 | |
|   } else {
 | |
|     mPrefs.Remove(aDomain);
 | |
|   }
 | |
| 
 | |
|   return RemoveContentPrefForDomain(aDomain, aIsPrivate);
 | |
| }
 | |
| 
 | |
| nsresult CookieBannerDomainPrefService::RemoveAll(bool aIsPrivate) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   // Don't do anything if we are shutting down.
 | |
|   if (NS_WARN_IF(mIsShuttingDown)) {
 | |
|     MOZ_LOG(gCookieBannerPerSitePrefLog, LogLevel::Warning,
 | |
|             ("Attempt to remove all domain prefs while shutting down."));
 | |
|     return NS_OK;
 | |
|   }
 | |
| 
 | |
|   EnsureInitCompleted(aIsPrivate);
 | |
| 
 | |
|   // Clear in-memory domain pref.
 | |
|   if (aIsPrivate) {
 | |
|     mPrefsPrivate.Clear();
 | |
|   } else {
 | |
|     mPrefs.Clear();
 | |
|   }
 | |
| 
 | |
|   nsCOMPtr<nsIContentPrefService2> contentPrefService =
 | |
|       do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
 | |
|   NS_ENSURE_TRUE(contentPrefService, NS_ERROR_FAILURE);
 | |
| 
 | |
|   auto callback = MakeRefPtr<WriteContentPrefCallback>(this);
 | |
|   mWritingCount++;
 | |
| 
 | |
|   // Remove all the domain preferences.
 | |
|   nsresult rv = contentPrefService->RemoveByName(
 | |
|       aIsPrivate ? COOKIE_BANNER_CONTENT_PREF_NAME_PRIVATE
 | |
|                  : COOKIE_BANNER_CONTENT_PREF_NAME,
 | |
|       nullptr, callback);
 | |
|   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
 | |
|                        "Fail to remove all cookie banner domain prefs.");
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| void CookieBannerDomainPrefService::EnsureInitCompleted(bool aIsPrivate) {
 | |
|   bool& isContentPrefLoaded =
 | |
|       aIsPrivate ? mIsPrivateContentPrefLoaded : mIsContentPrefLoaded;
 | |
|   if (isContentPrefLoaded) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Wait until the service is fully initialized.
 | |
|   SpinEventLoopUntil("CookieBannerDomainPrefService::EnsureUpdateComplete"_ns,
 | |
|                      [&] { return isContentPrefLoaded; });
 | |
| }
 | |
| 
 | |
| nsresult CookieBannerDomainPrefService::AddShutdownBlocker() {
 | |
|   MOZ_ASSERT(!mIsShuttingDown);
 | |
| 
 | |
|   nsCOMPtr<nsIAsyncShutdownClient> barrier = GetShutdownBarrier();
 | |
|   NS_ENSURE_TRUE(barrier, NS_ERROR_FAILURE);
 | |
| 
 | |
|   return GetShutdownBarrier()->AddBlocker(
 | |
|       this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__,
 | |
|       u"CookieBannerDomainPrefService: shutdown"_ns);
 | |
| }
 | |
| 
 | |
| nsresult CookieBannerDomainPrefService::RemoveShutdownBlocker() {
 | |
|   MOZ_ASSERT(mIsShuttingDown);
 | |
| 
 | |
|   nsCOMPtr<nsIAsyncShutdownClient> barrier = GetShutdownBarrier();
 | |
|   NS_ENSURE_TRUE(barrier, NS_ERROR_FAILURE);
 | |
| 
 | |
|   return GetShutdownBarrier()->RemoveBlocker(this);
 | |
| }
 | |
| 
 | |
| nsresult CookieBannerDomainPrefService::RemoveContentPrefForDomain(
 | |
|     const nsACString& aDomain, bool aIsPrivate) {
 | |
|   nsCOMPtr<nsIContentPrefService2> contentPrefService =
 | |
|       do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
 | |
|   NS_ENSURE_TRUE(contentPrefService, NS_ERROR_FAILURE);
 | |
| 
 | |
|   auto callback = MakeRefPtr<WriteContentPrefCallback>(this);
 | |
|   mWritingCount++;
 | |
| 
 | |
|   // Remove the domain preference from the content pref service.
 | |
|   nsresult rv = contentPrefService->RemoveByDomainAndName(
 | |
|       NS_ConvertUTF8toUTF16(aDomain),
 | |
|       aIsPrivate ? COOKIE_BANNER_CONTENT_PREF_NAME_PRIVATE
 | |
|                  : COOKIE_BANNER_CONTENT_PREF_NAME,
 | |
|       nullptr, callback);
 | |
|   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
 | |
|                        "Fail to remove cookie banner domain pref.");
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMPL_ISUPPORTS(CookieBannerDomainPrefService::BaseContentPrefCallback,
 | |
|                   nsIContentPrefCallback2)
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| CookieBannerDomainPrefService::InitialLoadContentPrefCallback::HandleResult(
 | |
|     nsIContentPref* aPref) {
 | |
|   NS_ENSURE_ARG_POINTER(aPref);
 | |
|   MOZ_ASSERT(mService);
 | |
| 
 | |
|   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);
 | |
| 
 | |
|   // Create the domain pref data and indicate it's persistent.
 | |
|   auto domainPrefData =
 | |
|       MakeRefPtr<DomainPrefData>(nsICookieBannerService::Modes(data), true);
 | |
| 
 | |
|   if (mIsPrivate) {
 | |
|     Unused << mService->mPrefsPrivate.InsertOrUpdate(
 | |
|         NS_ConvertUTF16toUTF8(domain), domainPrefData);
 | |
|   } else {
 | |
|     Unused << mService->mPrefs.InsertOrUpdate(NS_ConvertUTF16toUTF8(domain),
 | |
|                                               domainPrefData);
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| CookieBannerDomainPrefService::InitialLoadContentPrefCallback::HandleCompletion(
 | |
|     uint16_t aReason) {
 | |
|   MOZ_ASSERT(mService);
 | |
| 
 | |
|   if (mIsPrivate) {
 | |
|     mService->mIsPrivateContentPrefLoaded = true;
 | |
|   } else {
 | |
|     mService->mIsContentPrefLoaded = true;
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| CookieBannerDomainPrefService::InitialLoadContentPrefCallback::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;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| CookieBannerDomainPrefService::WriteContentPrefCallback::HandleResult(
 | |
|     nsIContentPref* aPref) {
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| CookieBannerDomainPrefService::WriteContentPrefCallback::HandleCompletion(
 | |
|     uint16_t aReason) {
 | |
|   MOZ_ASSERT(mService);
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   MOZ_ASSERT(mService->mWritingCount > 0);
 | |
| 
 | |
|   mService->mWritingCount--;
 | |
| 
 | |
|   // Remove the shutdown blocker after we complete writing to content pref.
 | |
|   if (mService->mIsShuttingDown && mService->mWritingCount == 0) {
 | |
|     mService->RemoveShutdownBlocker();
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| CookieBannerDomainPrefService::WriteContentPrefCallback::HandleError(
 | |
|     nsresult error) {
 | |
|   if (NS_WARN_IF(NS_FAILED(error))) {
 | |
|     MOZ_LOG(gCookieBannerPerSitePrefLog, LogLevel::Warning,
 | |
|             ("Fail to write content pref."));
 | |
|     return NS_OK;
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| CookieBannerDomainPrefService::Observe(nsISupports* /*aSubject*/,
 | |
|                                        const char* aTopic,
 | |
|                                        const char16_t* /*aData*/) {
 | |
|   if (strcmp(aTopic, "last-pb-context-exited") != 0) {
 | |
|     MOZ_ASSERT_UNREACHABLE("unexpected topic");
 | |
|     return NS_ERROR_UNEXPECTED;
 | |
|   }
 | |
| 
 | |
|   // Clear the private browsing domain prefs that are not persistent when we
 | |
|   // observe the private browsing session has ended.
 | |
|   mPrefsPrivate.RemoveIf([](const auto& iter) {
 | |
|     const RefPtr<DomainPrefData>& data = iter.Data();
 | |
|     return !data->mIsPersistent;
 | |
|   });
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| CookieBannerDomainPrefService::GetName(nsAString& aName) {
 | |
|   aName.AssignLiteral(
 | |
|       "CookieBannerDomainPrefService: write content pref before "
 | |
|       "profile-before-change.");
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| CookieBannerDomainPrefService::BlockShutdown(nsIAsyncShutdownClient*) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
| 
 | |
|   mIsShuttingDown = true;
 | |
| 
 | |
|   // If we are not writing the content pref, we can remove the shutdown blocker
 | |
|   // directly.
 | |
|   if (mWritingCount == 0) {
 | |
|     RemoveShutdownBlocker();
 | |
|   }
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| CookieBannerDomainPrefService::GetState(nsIPropertyBag**) { return NS_OK; }
 | |
| 
 | |
| }  // namespace mozilla
 |