/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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 DOM_QUOTA_CLIENTSTORAGESCOPE_H_ #define DOM_QUOTA_CLIENTSTORAGESCOPE_H_ #include "mozilla/Assertions.h" #include "mozilla/Variant.h" #include "mozilla/dom/quota/Client.h" namespace mozilla::dom::quota { /** * Represents a scope within an origin directory, currently covering either a * specific client (`Client`), metadata (`Metadata`), or a match-all scope * (`Null`). * * The use of "Storage" in the class name is intentional. Unlike * `PersistenceScope` and `OriginScope`, which match only specific directories, * this scope is meant to cover all entries within an origin directory. That * includes client specific folders (e.g., idb/, fs/) and, in the future, files * like metadata that exist alongside them. * * The special `Metadata` scope exists because adding the metadata type to * client types would complicate other aspects of the system. A special client * implementation just for working with the metadata file would be overkill. * However, we need a way to lock just the metadata file. Since metadata files * reside alongside client directories under the same origin directory, it * makes sense to include them in the `ClientStorageScope`. * * This class provides operations to check the current scope type * (`Client`, `Metadata`, or `Null`), set the scope type, retrieve a client * type, and match it with another scope. */ class ClientStorageScope { class Client { quota::Client::Type mClientType; public: explicit Client(quota::Client::Type aClientType) : mClientType(aClientType) {} quota::Client::Type GetClientType() const { return mClientType; } }; struct Metadata {}; struct Null {}; using DataType = Variant; DataType mData; public: ClientStorageScope() : mData(Null()) {} static ClientStorageScope CreateFromClient(quota::Client::Type aClientType) { return ClientStorageScope(std::move(Client(aClientType))); } static ClientStorageScope CreateFromMetadata() { return ClientStorageScope(std::move(Metadata())); } static ClientStorageScope CreateFromNull() { return ClientStorageScope(std::move(Null())); } bool IsClient() const { return mData.is(); } bool IsMetadata() const { return mData.is(); } bool IsNull() const { return mData.is(); } void SetFromClient(quota::Client::Type aClientType) { mData = AsVariant(Client(aClientType)); } void SetFromNull() { mData = AsVariant(Null()); } quota::Client::Type GetClientType() const { MOZ_ASSERT(IsClient()); return mData.as().GetClientType(); } bool Matches(const ClientStorageScope& aOther) const { struct Matcher { const ClientStorageScope& mThis; explicit Matcher(const ClientStorageScope& aThis) : mThis(aThis) {} bool operator()(const Client& aOther) { return mThis.MatchesClient(aOther); } bool operator()(const Metadata& aOther) { return mThis.MatchesMetadata(aOther); } bool operator()(const Null& aOther) { return true; } }; return aOther.mData.match(Matcher(*this)); } private: // Move constructors explicit ClientStorageScope(const Client&& aClient) : mData(aClient) {} explicit ClientStorageScope(const Metadata&& aMetadata) : mData(aMetadata) {} explicit ClientStorageScope(const Null&& aNull) : mData(aNull) {} // Copy constructor explicit ClientStorageScope(const DataType& aOther) : mData(aOther) {} bool MatchesClient(const Client& aOther) const { struct ClientMatcher { const Client& mOther; explicit ClientMatcher(const Client& aOther) : mOther(aOther) {} bool operator()(const Client& aThis) { return aThis.GetClientType() == mOther.GetClientType(); } bool operator()(const Metadata& aThis) { return false; } bool operator()(const Null& aThis) { // Null covers everything. return true; } }; return mData.match(ClientMatcher(aOther)); } bool MatchesMetadata(const Metadata& aOther) const { struct MetadataMatcher { const Metadata& mOther; explicit MetadataMatcher(const Metadata& aOther) : mOther(aOther) {} bool operator()(const Client& aThis) { return false; } bool operator()(const Metadata& aThis) { return true; } bool operator()(const Null& aThis) { // Null covers everything. return true; } }; return mData.match(MetadataMatcher(aOther)); } bool operator==(const ClientStorageScope& aOther) = delete; }; } // namespace mozilla::dom::quota #endif // DOM_QUOTA_CLIENTSTORAGESCOPE_H_