From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- toolkit/components/extensions/MatchPattern.h | 403 +++++++++++++++++++++++++++ 1 file changed, 403 insertions(+) create mode 100644 toolkit/components/extensions/MatchPattern.h (limited to 'toolkit/components/extensions/MatchPattern.h') diff --git a/toolkit/components/extensions/MatchPattern.h b/toolkit/components/extensions/MatchPattern.h new file mode 100644 index 0000000000..ebfd1c62a1 --- /dev/null +++ b/toolkit/components/extensions/MatchPattern.h @@ -0,0 +1,403 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ +/* 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_extensions_MatchPattern_h +#define mozilla_extensions_MatchPattern_h + +#include + +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/MatchPatternBinding.h" +#include "mozilla/extensions/MatchGlob.h" + +#include "jspubtd.h" + +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/Likely.h" +#include "mozilla/Maybe.h" +#include "mozilla/RefCounted.h" +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsTArray.h" +#include "nsAtom.h" +#include "nsICookie.h" +#include "nsISupports.h" +#include "nsIURI.h" +#include "nsWrapperCache.h" + +namespace mozilla { +namespace extensions { + +using dom::MatchPatternOptions; + +// A sorted, immutable, binary-search-backed set of atoms, optimized for +// frequent lookups. +class AtomSet final { + public: + using ArrayType = AutoTArray, 1>; + + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AtomSet) + + explicit AtomSet(const nsTArray& aElems); + + MOZ_IMPLICIT AtomSet(std::initializer_list aIL); + + bool Contains(const nsAString& elem) const { + RefPtr atom = NS_Atomize(elem); + return Contains(atom); + } + + bool Contains(const nsACString& aElem) const { + RefPtr atom = NS_Atomize(aElem); + return Contains(atom); + } + + bool Contains(const nsAtom* aAtom) const { + return mElems.ContainsSorted(aAtom); + } + + bool Intersects(const AtomSet& aOther) const; + + void Get(nsTArray& aResult) const { + aResult.SetCapacity(mElems.Length()); + + for (const auto& atom : mElems) { + aResult.AppendElement(nsDependentAtomString(atom)); + } + } + + auto begin() const -> decltype(std::declval().begin()) { + return mElems.begin(); + } + + auto end() const -> decltype(std::declval().end()) { + return mElems.end(); + } + + private: + ~AtomSet() = default; + + const ArrayType mElems; +}; + +// A helper class to lazily retrieve, transcode, and atomize certain URI +// properties the first time they're used, and cache the results, so that they +// can be used across multiple match operations. +class URLInfo final { + public: + MOZ_IMPLICIT URLInfo(nsIURI* aURI) : mURI(aURI) { mHost.SetIsVoid(true); } + + URLInfo(nsIURI* aURI, bool aNoRef) : URLInfo(aURI) { + if (aNoRef) { + mURINoRef = mURI; + } + } + + URLInfo(const URLInfo& aOther) : URLInfo(aOther.mURI.get()) {} + + nsIURI* URI() const { return mURI; } + + nsAtom* Scheme() const; + const nsCString& Host() const; + const nsAtom* HostAtom() const; + const nsCString& Path() const; + const nsCString& FilePath() const; + const nsString& Spec() const; + const nsCString& CSpec() const; + + bool InheritsPrincipal() const; + + private: + nsIURI* URINoRef() const; + + nsCOMPtr mURI; + mutable nsCOMPtr mURINoRef; + + mutable RefPtr mScheme; + mutable nsCString mHost; + mutable RefPtr mHostAtom; + + mutable nsCString mPath; + mutable nsCString mFilePath; + mutable nsString mSpec; + mutable nsCString mCSpec; + + mutable Maybe mInheritsPrincipal; +}; + +// Similar to URLInfo, but for cookies. +class MOZ_STACK_CLASS CookieInfo final { + public: + MOZ_IMPLICIT CookieInfo(nsICookie* aCookie) : mCookie(aCookie) {} + + bool IsSecure() const; + bool IsDomain() const; + + const nsCString& Host() const; + const nsCString& RawHost() const; + + private: + nsCOMPtr mCookie; + + mutable Maybe mIsSecure; + mutable Maybe mIsDomain; + + mutable nsCString mHost; + mutable nsCString mRawHost; +}; + +class MatchPatternCore final { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MatchPatternCore) + + // NOTE: Must be constructed on the main thread! + MatchPatternCore(const nsAString& aPattern, bool aIgnorePath, + bool aRestrictSchemes, ErrorResult& aRv); + + bool Matches(const nsAString& aURL, bool aExplicit, ErrorResult& aRv) const; + + bool Matches(const URLInfo& aURL, bool aExplicit = false) const; + + bool MatchesAllWebUrls() const; + // Helper for MatchPatternSetCore::MatchesAllWebUrls: + bool MatchesAllUrlsWithScheme(const nsAtom* aScheme) const; + + bool MatchesCookie(const CookieInfo& aCookie) const; + + bool MatchesDomain(const nsACString& aDomain) const; + + bool Subsumes(const MatchPatternCore& aPattern) const; + + bool SubsumesDomain(const MatchPatternCore& aPattern) const; + + bool Overlaps(const MatchPatternCore& aPattern) const; + + bool DomainIsWildcard() const { return mMatchSubdomain && mDomain.IsEmpty(); } + + void GetPattern(nsAString& aPattern) const { aPattern = mPattern; } + + private: + ~MatchPatternCore() = default; + + // The normalized match pattern string that this object represents. + nsString mPattern; + + // The set of atomized URI schemes that this pattern matches. + RefPtr mSchemes; + + // The domain that this matcher matches. If mMatchSubdomain is false, only + // matches the exact domain. If it's true, matches the domain or any + // subdomain. + // + // For instance, "*.foo.com" gives mDomain = "foo.com" and mMatchSubdomain = + // true, and matches "foo.com" or "bar.foo.com" but not "barfoo.com". + // + // While "foo.com" gives mDomain = "foo.com" and mMatchSubdomain = false, + // and matches "foo.com" but not "bar.foo.com". + nsCString mDomain; + bool mMatchSubdomain = false; + + // The glob against which the URL path must match. If null, the path is + // ignored entirely. If non-null, the path must match this glob. + RefPtr mPath; +}; + +class MatchPattern final : public nsISupports, public nsWrapperCache { + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(MatchPattern) + + static already_AddRefed Constructor( + dom::GlobalObject& aGlobal, const nsAString& aPattern, + const MatchPatternOptions& aOptions, ErrorResult& aRv); + + bool Matches(const nsAString& aURL, bool aExplicit, ErrorResult& aRv) const { + return Core()->Matches(aURL, aExplicit, aRv); + } + + bool MatchesAllWebUrls() const { return Core()->MatchesAllWebUrls(); } + + bool Matches(const URLInfo& aURL, bool aExplicit = false) const { + return Core()->Matches(aURL, aExplicit); + } + + bool Matches(const URLInfo& aURL, bool aExplicit, ErrorResult& aRv) const { + return Matches(aURL, aExplicit); + } + + bool MatchesCookie(const CookieInfo& aCookie) const { + return Core()->MatchesCookie(aCookie); + } + + bool MatchesDomain(const nsACString& aDomain) const { + return Core()->MatchesDomain(aDomain); + } + + bool Subsumes(const MatchPattern& aPattern) const { + return Core()->Subsumes(*aPattern.Core()); + } + + bool SubsumesDomain(const MatchPattern& aPattern) const { + return Core()->SubsumesDomain(*aPattern.Core()); + } + + bool Overlaps(const MatchPattern& aPattern) const { + return Core()->Overlaps(*aPattern.Core()); + } + + bool DomainIsWildcard() const { return Core()->DomainIsWildcard(); } + + void GetPattern(nsAString& aPattern) const { Core()->GetPattern(aPattern); } + + MatchPatternCore* Core() const { return mCore; } + + nsISupports* GetParentObject() const { return mParent; } + + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + + protected: + virtual ~MatchPattern() = default; + + private: + friend class MatchPatternSet; + + explicit MatchPattern(nsISupports* aParent, + already_AddRefed aCore) + : mParent(aParent), mCore(std::move(aCore)) {} + + void Init(JSContext* aCx, const nsAString& aPattern, bool aIgnorePath, + bool aRestrictSchemes, ErrorResult& aRv); + + nsCOMPtr mParent; + + RefPtr mCore; + + public: + // A quick way to check if a particular URL matches without + // actually instantiating a MatchPattern + static bool MatchesAllURLs(const URLInfo& aURL); +}; + +class MatchPatternSetCore final { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MatchPatternSetCore) + + using ArrayType = nsTArray>; + + explicit MatchPatternSetCore(ArrayType&& aPatterns) + : mPatterns(std::move(aPatterns)) {} + + static already_AddRefed Constructor( + dom::GlobalObject& aGlobal, + const nsTArray& aPatterns, + const MatchPatternOptions& aOptions, ErrorResult& aRv); + + bool Matches(const nsAString& aURL, bool aExplicit, ErrorResult& aRv) const; + + bool Matches(const URLInfo& aURL, bool aExplicit = false) const; + + bool MatchesAllWebUrls() const; + + bool MatchesCookie(const CookieInfo& aCookie) const; + + bool Subsumes(const MatchPatternCore& aPattern) const; + + bool SubsumesDomain(const MatchPatternCore& aPattern) const; + + bool Overlaps(const MatchPatternCore& aPattern) const; + + bool Overlaps(const MatchPatternSetCore& aPatternSet) const; + + bool OverlapsAll(const MatchPatternSetCore& aPatternSet) const; + + void GetPatterns(ArrayType& aPatterns) { + aPatterns.AppendElements(mPatterns); + } + + private: + friend class MatchPatternSet; + + ~MatchPatternSetCore() = default; + + ArrayType mPatterns; +}; + +class MatchPatternSet final : public nsISupports, public nsWrapperCache { + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(MatchPatternSet) + + using ArrayType = nsTArray>; + + static already_AddRefed Constructor( + dom::GlobalObject& aGlobal, + const nsTArray& aPatterns, + const MatchPatternOptions& aOptions, ErrorResult& aRv); + + bool Matches(const nsAString& aURL, bool aExplicit, ErrorResult& aRv) const { + return Core()->Matches(aURL, aExplicit, aRv); + } + + bool Matches(const URLInfo& aURL, bool aExplicit = false) const { + return Core()->Matches(aURL, aExplicit); + } + + bool Matches(const URLInfo& aURL, bool aExplicit, ErrorResult& aRv) const { + return Matches(aURL, aExplicit); + } + + bool MatchesAllWebUrls() const { return Core()->MatchesAllWebUrls(); } + + bool MatchesCookie(const CookieInfo& aCookie) const { + return Core()->MatchesCookie(aCookie); + } + + bool Subsumes(const MatchPattern& aPattern) const { + return Core()->Subsumes(*aPattern.Core()); + } + + bool SubsumesDomain(const MatchPattern& aPattern) const { + return Core()->SubsumesDomain(*aPattern.Core()); + } + + bool Overlaps(const MatchPattern& aPattern) const { + return Core()->Overlaps(*aPattern.Core()); + } + + bool Overlaps(const MatchPatternSet& aPatternSet) const { + return Core()->Overlaps(*aPatternSet.Core()); + } + + bool OverlapsAll(const MatchPatternSet& aPatternSet) const { + return Core()->OverlapsAll(*aPatternSet.Core()); + } + + void GetPatterns(ArrayType& aPatterns); + + MatchPatternSetCore* Core() const { return mCore; } + + nsISupports* GetParentObject() const { return mParent; } + + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + + protected: + virtual ~MatchPatternSet() = default; + + private: + explicit MatchPatternSet(nsISupports* aParent, + already_AddRefed aCore) + : mParent(aParent), mCore(std::move(aCore)) {} + + nsCOMPtr mParent; + + RefPtr mCore; + + mozilla::Maybe mPatternsCache; +}; + +} // namespace extensions +} // namespace mozilla + +#endif // mozilla_extensions_MatchPattern_h -- cgit v1.2.3