Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  CookieStoreSubscriptionService.cpp

  Sprache: 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 "CookieStoreSubscriptionService.h"

#include "json/json.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/PCookieStore.h"
#include "mozilla/dom/ServiceWorkerManager.h"
#include "mozilla/dom/ServiceWorkerRegistrar.h"
#include "mozilla/net/Cookie.h"
#include "mozilla/net/CookieCommons.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsICookieNotification.h"

using namespace mozilla::dom;
using namespace mozilla::net;
using mozilla::ipc::PrincipalInfo;

static mozilla::StaticRefPtr<CookieStoreSubscriptionService> gService;

NS_IMPL_ISUPPORTS(CookieStoreSubscriptionService, nsIObserver)

// static
void CookieStoreSubscriptionService::ServiceWorkerLoaded(
    const ServiceWorkerRegistrationData& aData, const nsACString& aValue) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(XRE_IsParentProcess());

  CookieStoreSubscriptionService* service =
      CookieStoreSubscriptionService::Instance();
  service->Load(aData, aValue);
}

// static
void CookieStoreSubscriptionService::ServiceWorkerUpdated(
    const ServiceWorkerRegistrationData& aData) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(XRE_IsParentProcess());

  // This is a no-op
}

// static
void CookieStoreSubscriptionService::ServiceWorkerUnregistered(
    const ServiceWorkerRegistrationData& aData) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(XRE_IsParentProcess());

  CookieStoreSubscriptionService* service =
      CookieStoreSubscriptionService::Instance();
  service->Unregister(aData);
}
// static
void CookieStoreSubscriptionService::ServiceWorkerUnregistered(
    nsIPrincipal* aPrincipal, const nsACString& aScopeURL) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(XRE_IsParentProcess());

  PrincipalInfo principalInfo;
  nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return;
  }

  ServiceWorkerRegistrationData tmp;
  tmp.principal() = principalInfo;
  tmp.scope() = aScopeURL;

  CookieStoreSubscriptionService* service =
      CookieStoreSubscriptionService::Instance();
  service->Unregister(tmp);
}

// static
CookieStoreSubscriptionService* CookieStoreSubscriptionService::Instance() {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(XRE_IsParentProcess());

  if (!gService && !PastShutdownPhase(ShutdownPhase::XPCOMShutdownFinal)) {
    gService = new CookieStoreSubscriptionService();
    gService->Initialize();
    ClearOnShutdown(&gService, ShutdownPhase::XPCOMShutdownFinal);
  }

  return gService;
}

CookieStoreSubscriptionService::CookieStoreSubscriptionService() {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(XRE_IsParentProcess());
}

void CookieStoreSubscriptionService::Initialize() {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(XRE_IsParentProcess());

  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  if (obs) {
    DebugOnly<nsresult> rv =
        obs->AddObserver(gService, "private-cookie-changed"false);
    MOZ_ASSERT(NS_SUCCEEDED(rv));

    rv = obs->AddObserver(gService, "cookie-changed"false);
    MOZ_ASSERT(NS_SUCCEEDED(rv));
  }
}

namespace {

bool Equivalent(const ServiceWorkerRegistrationData& aLeft,
                const ServiceWorkerRegistrationData& aRight) {
  MOZ_ASSERT(aLeft.principal().type() == PrincipalInfo::TContentPrincipalInfo);
  MOZ_ASSERT(aRight.principal().type() == PrincipalInfo::TContentPrincipalInfo);

  const auto& leftPrincipal = aLeft.principal().get_ContentPrincipalInfo();
  const auto& rightPrincipal = aRight.principal().get_ContentPrincipalInfo();

  // Only compare the attributes, not the spec part of the principal.
  // The scope comparison above already covers the origin and codebase
  // principals include the full path in their spec which is not what
  // we want here.
  return aLeft.scope() == aRight.scope() &&
         leftPrincipal.attrs() == rightPrincipal.attrs();
}

}  // anonymous namespace

void CookieStoreSubscriptionService::GetSubscriptions(
    const PrincipalInfo& aPrincipalInfo, const nsACString& aScope,
    nsTArray<CookieSubscription>& aSubscriptions) {
  MOZ_ASSERT(NS_IsMainThread());

  ServiceWorkerRegistrationData tmp;
  tmp.principal() = aPrincipalInfo;
  tmp.scope() = aScope;

  for (const RegistrationData& data : mData) {
    if (Equivalent(tmp, data.mRegistration)) {
      aSubscriptions.AppendElements(data.mSubscriptions);
      break;
    }
  }
}

void CookieStoreSubscriptionService::Subscribe(
    const PrincipalInfo& aPrincipalInfo, const nsACString& aScope,
    const nsTArray<CookieSubscription>& aSubscriptions) {
  MOZ_ASSERT(NS_IsMainThread());

  ServiceWorkerRegistrationData tmp;
  tmp.principal() = aPrincipalInfo;
  tmp.scope() = aScope;

  RegistrationData* registrationData = nullptr;

  for (RegistrationData& data : mData) {
    if (Equivalent(tmp, data.mRegistration)) {
      registrationData = &data;
      break;
    }
  }

  if (!registrationData) {
    registrationData = mData.AppendElement();
    registrationData->mRegistration = tmp;
  }

  bool toStore = false;

  for (const CookieSubscription& subscription : aSubscriptions) {
    bool found = false;
    for (const CookieSubscription& existingSubscription :
         registrationData->mSubscriptions) {
      if (existingSubscription.name() == subscription.name() &&
          existingSubscription.url() == subscription.url()) {
        // Nothing to do.
        found = true;
        break;
      }
    }

    if (!found) {
      registrationData->mSubscriptions.AppendElement(subscription);
      toStore = true;
    }
  }

  if (toStore) {
    SerializeAndSave(*registrationData);
  }
}

void CookieStoreSubscriptionService::Unsubscribe(
    const PrincipalInfo& aPrincipalInfo, const nsACString& aScope,
    const nsTArray<CookieSubscription>& aSubscriptions) {
  MOZ_ASSERT(NS_IsMainThread());

  ServiceWorkerRegistrationData tmp;
  tmp.principal() = aPrincipalInfo;
  tmp.scope() = aScope;

  RegistrationData* registrationData = nullptr;
  uint32_t registrationDataId = 0;

  for (; registrationDataId < mData.Length(); ++registrationDataId) {
    RegistrationData& data = mData[registrationDataId];
    if (Equivalent(tmp, data.mRegistration)) {
      registrationData = &data;
      break;
    }
  }

  if (!registrationData) {
    return;
  }

  bool toStore = false;

  for (const CookieSubscription& subscription : aSubscriptions) {
    for (uint32_t i = 0; i < registrationData->mSubscriptions.Length(); ++i) {
      const CookieSubscription& existingSubscription =
          registrationData->mSubscriptions[i];
      if (existingSubscription.name() == subscription.name() &&
          existingSubscription.url() == subscription.url()) {
        registrationData->mSubscriptions.RemoveElementAt(i);
        toStore = true;
        break;
      }
    }
  }

  if (toStore) {
    SerializeAndSave(*registrationData);

    if (registrationData->mSubscriptions.IsEmpty()) {
      mData.RemoveElementAt(registrationDataId);
    }
  }
}

NS_IMETHODIMP
CookieStoreSubscriptionService::Observe(nsISupports* aSubject,
                                        const char* aTopic,
                                        const char16_t* aData) {
  MOZ_ASSERT(NS_IsMainThread());

  nsCOMPtr<nsICookieNotification> notification = do_QueryInterface(aSubject);
  NS_ENSURE_TRUE(notification, NS_ERROR_FAILURE);

  auto action = notification->GetAction();
  if (action != nsICookieNotification::COOKIE_DELETED &&
      action != nsICookieNotification::COOKIE_ADDED &&
      action != nsICookieNotification::COOKIE_CHANGED) {
    // Other actions are user specific ones (ALL_COOKIES_CLEARED or
    // COOKIES_BATCH_DELETED) and we don't want to expose them here.
    return NS_OK;
  }

  nsAutoCString baseDomain;
  nsresult rv = notification->GetBaseDomain(baseDomain);
  if (NS_WARN_IF(NS_FAILED(rv)) || baseDomain.IsEmpty()) {
    return rv;
  }

  nsCOMPtr<nsICookie> cookie;
  rv = notification->GetCookie(getter_AddRefs(cookie));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  bool isHttpOnly;
  rv = cookie->GetIsHttpOnly(&isHttpOnly);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (isHttpOnly) {
    return NS_OK;
  }

  nsAutoCString nameUtf8;
  rv = cookie->GetName(nameUtf8);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  NS_ConvertUTF8toUTF16 name(nameUtf8);

  bool deleteEvent = action == nsICookieNotification::COOKIE_DELETED;

  nsAutoString value;
  if (!deleteEvent) {
    nsAutoCString valueUtf8;
    rv = cookie->GetValue(valueUtf8);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }

    CopyUTF8toUTF16(valueUtf8, value);
  }

  RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
  if (!swm) {
    return NS_ERROR_FAILURE;
  }

  for (const RegistrationData& data : mData) {
    MOZ_ASSERT(data.mRegistration.principal().type() ==
               PrincipalInfo::TContentPrincipalInfo);

    const auto& principalInfo =
        data.mRegistration.principal().get_ContentPrincipalInfo();

    if (principalInfo.baseDomain() != baseDomain) {
      continue;
    }

    if (cookie->OriginAttributesNative() != principalInfo.attrs()) {
      continue;
    }

    for (const CookieSubscription& subscription : data.mSubscriptions) {
      if (subscription.name().isSome() && subscription.name().value() != name) {
        continue;
      }

      nsCOMPtr<nsIURI> uri;
      rv = NS_NewURI(getter_AddRefs(uri), data.mRegistration.scope());
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return rv;
      }

      nsAutoCString filePath;
      rv = uri->GetFilePath(filePath);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return rv;
      }

      if (!CookieCommons::PathMatches(cookie->AsCookie().Path(), filePath)) {
        continue;
      }

      rv = swm->SendCookieChangeEvent(principalInfo.attrs(),
                                      data.mRegistration.scope(),
                                      cookie->AsCookie().ToIPC(), deleteEvent);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return rv;
      }

      break;
    }
  }

  return NS_OK;
}

void CookieStoreSubscriptionService::Load(
    const ServiceWorkerRegistrationData& aData, const nsACString& aValue) {
  MOZ_ASSERT(NS_IsMainThread());

  for (RegistrationData& data : mData) {
    if (Equivalent(aData, data.mRegistration)) {
      ParseAndAddSubscription(data, aValue);
      return;
    }
  }

  RegistrationData* data = mData.AppendElement();
  data->mRegistration = aData;
  ParseAndAddSubscription(*data, aValue);
}

void CookieStoreSubscriptionService::Unregister(
    const ServiceWorkerRegistrationData& aData) {
  MOZ_ASSERT(NS_IsMainThread());

  for (uint32_t i = 0; i < mData.Length(); ++i) {
    if (Equivalent(aData, mData[i].mRegistration)) {
      mData.RemoveElementAt(i);
      return;
    }
  }
}

void CookieStoreSubscriptionService::ParseAndAddSubscription(
    RegistrationData& aData, const nsACString& aValue) {
  MOZ_ASSERT(NS_IsMainThread());

  Json::Value value;
  Json::Reader jsonReader;

  MOZ_ASSERT(jsonReader.parse(aValue.BeginReading(), aValue.EndReading(), value,
                              false));
  MOZ_ASSERT(value.isObject());

  for (Json::ValueConstIterator iter = value.begin(); iter != value.end();
       ++iter) {
    CookieSubscription* subscription = aData.mSubscriptions.AppendElement();

    for (Json::Value::const_iterator itr = iter->begin(); itr != iter->end();
         itr++) {
      MOZ_ASSERT(iter.key().isString());
      MOZ_ASSERT(iter->isString());
      if (itr.key().asString().compare("name") == 0) {
        subscription->name() =
            Some(NS_ConvertUTF8toUTF16(iter->asString().c_str()));
      } else if (itr.key().asString().compare("url") == 0) {
        subscription->url() = NS_ConvertUTF8toUTF16(iter->asString().c_str());
      }
    }
  }
}

void CookieStoreSubscriptionService::SerializeAndSave(
    const RegistrationData& aData) {
  MOZ_ASSERT(NS_IsMainThread());

  RefPtr<ServiceWorkerRegistrar> swr = ServiceWorkerRegistrar::Get();
  MOZ_ASSERT(swr);

  if (aData.mSubscriptions.IsEmpty()) {
    swr->UnstoreServiceWorkerExpandoOnMainThread(
        aData.mRegistration.principal(), aData.mRegistration.scope(),
        nsCString("cookie-store"));
    return;
  }

  Json::Value root;
  Json::StreamWriterBuilder builder;
  builder["indentation"] = "";
  const std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());

  for (uint32_t i = 0; i < aData.mSubscriptions.Length(); ++i) {
    Json::Value entry;

    if (aData.mSubscriptions[i].name().isSome()) {
      entry["name"] =
          NS_ConvertUTF16toUTF8(aData.mSubscriptions[i].name().value()).get();
    }

    entry["url"] = NS_ConvertUTF16toUTF8(aData.mSubscriptions[i].url()).get();
    root[i] = entry;
  }

  std::string document = Json::writeString(builder, root);

  swr->StoreServiceWorkerExpandoOnMainThread(
      aData.mRegistration.principal(), aData.mRegistration.scope(),
      nsCString("cookie-store"), nsCString(document));
}

Messung V0.5 in Prozent
C=83 H=92 G=87

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002