/* -*- 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 mozilla_dom_SharedScriptCache_h #define mozilla_dom_SharedScriptCache_h #include "PLDHashTable.h" // PLDHashEntryHdr #include "js/loader/LoadedScript.h" // JS::loader::LoadedScript #include "js/loader/ScriptKind.h" // JS::loader::ScriptKind #include "js/loader/ScriptLoadRequest.h" // JS::loader::ScriptLoadRequest #include "mozilla/RefPtr.h" // RefPtr #include "mozilla/WeakPtr.h" // SupportsWeakPtr #include "mozilla/CORSMode.h" // mozilla::CORSMode #include "mozilla/MemoryReporting.h" // MallocSizeOf #include "mozilla/SharedSubResourceCache.h" // SharedSubResourceCache, SharedSubResourceCacheLoadingValueBase, SubResourceNetworkMetadataHolder #include "mozilla/dom/CacheExpirationTime.h" // CacheExpirationTime #include "nsIMemoryReporter.h" // nsIMemoryReporter, NS_DECL_NSIMEMORYREPORTER #include "nsIObserver.h" // nsIObserver, NS_DECL_NSIOBSERVER #include "nsIPrincipal.h" // nsIPrincipal #include "nsISupports.h" // nsISupports, NS_DECL_ISUPPORTS #include "nsStringFwd.h" // nsACString #include "mozilla/dom/SRIMetadata.h" // mozilla::dom::SRIMetadata namespace mozilla { namespace dom { class ScriptLoader; class ScriptLoadData; class ScriptHashKey : public PLDHashEntryHdr { public: using KeyType = const ScriptHashKey&; using KeyTypePointer = const ScriptHashKey*; explicit ScriptHashKey(const ScriptHashKey& aKey) : PLDHashEntryHdr(), mURI(aKey.mURI), mLoaderPrincipal(aKey.mLoaderPrincipal), mPartitionPrincipal(aKey.mPartitionPrincipal), mCORSMode(aKey.mCORSMode), mSRIMetadata(aKey.mSRIMetadata), mKind(aKey.mKind), mNonce(aKey.mNonce), mHintCharset(aKey.mHintCharset), mIsLinkRelPreload(aKey.mIsLinkRelPreload) { MOZ_COUNT_CTOR(ScriptHashKey); } explicit ScriptHashKey(const ScriptHashKey* aKey) : ScriptHashKey(*aKey) {} ScriptHashKey(ScriptHashKey&& aKey) : PLDHashEntryHdr(), mURI(std::move(aKey.mURI)), mLoaderPrincipal(std::move(aKey.mLoaderPrincipal)), mPartitionPrincipal(std::move(aKey.mPartitionPrincipal)), mCORSMode(std::move(aKey.mCORSMode)), mSRIMetadata(std::move(aKey.mSRIMetadata)), mKind(std::move(aKey.mKind)), mNonce(std::move(aKey.mNonce)), mHintCharset(std::move(aKey.mHintCharset)), mIsLinkRelPreload(std::move(aKey.mIsLinkRelPreload)) { MOZ_COUNT_CTOR(ScriptHashKey); } ScriptHashKey(ScriptLoader* aLoader, const JS::loader::ScriptLoadRequest* aRequest); explicit ScriptHashKey(const ScriptLoadData& aLoadData); MOZ_COUNTED_DTOR(ScriptHashKey) const ScriptHashKey& GetKey() const { return *this; } const ScriptHashKey* GetKeyPointer() const { return this; } bool KeyEquals(const ScriptHashKey* aKey) const { return KeyEquals(*aKey); } bool KeyEquals(const ScriptHashKey&) const; static const ScriptHashKey* KeyToPointer(const ScriptHashKey& aKey) { return &aKey; } static PLDHashNumber HashKey(const ScriptHashKey* aKey) { return nsURIHashKey::HashKey(aKey->mURI); } nsIPrincipal* LoaderPrincipal() const { return mLoaderPrincipal; } nsIPrincipal* PartitionPrincipal() const { return mPartitionPrincipal; } nsIURI* URI() const { return mURI; } enum { ALLOW_MEMMOVE = true }; protected: const nsCOMPtr mURI; const nsCOMPtr mLoaderPrincipal; const nsCOMPtr mPartitionPrincipal; const CORSMode mCORSMode; const SRIMetadata mSRIMetadata; const JS::loader::ScriptKind mKind; const nsString mNonce; // charset attribute for classic script. // module always use UTF-8. nsString mHintCharset; // TODO: Reflect URL classifier data source. // mozilla::dom::ContentType // maybe implicit // top-level document's host // maybe part of principal? // what if it's inside frame in different host? const bool mIsLinkRelPreload; }; class ScriptLoadData final : public SupportsWeakPtr, public nsISupports, public SharedSubResourceCacheLoadingValueBase { protected: ~ScriptLoadData() {} public: ScriptLoadData(ScriptLoader* aLoader, JS::loader::ScriptLoadRequest* aRequest); NS_DECL_ISUPPORTS // Only completed loads are used for the cache. bool IsLoading() const override { return false; } bool IsCancelled() const override { return false; } bool IsSyncLoad() const override { return true; } SubResourceNetworkMetadataHolder* GetNetworkMetadata() const override { return mNetworkMetadata.get(); } void StartLoading() override {} void SetLoadCompleted() override {} void OnCoalescedTo(const ScriptLoadData& aExistingLoad) override {} void Cancel() override {} void DidCancelLoad() {} bool ShouldDefer() const { return false; } JS::loader::LoadedScript* ValueForCache() const { return mLoadedScript.get(); } const CacheExpirationTime& ExpirationTime() const { return mExpirationTime; } ScriptLoader& Loader() { return *mLoader; } const ScriptHashKey& CacheKey() const { return mKey; } private: CacheExpirationTime mExpirationTime = CacheExpirationTime::Never(); ScriptLoader* mLoader; ScriptHashKey mKey; RefPtr mLoadedScript; RefPtr mNetworkMetadata; }; struct SharedScriptCacheTraits { using Loader = ScriptLoader; using Key = ScriptHashKey; using Value = JS::loader::LoadedScript; using LoadingValue = ScriptLoadData; static ScriptHashKey KeyFromLoadingValue(const LoadingValue& aValue) { return ScriptHashKey(aValue); } }; class SharedScriptCache final : public SharedSubResourceCache, public nsIMemoryReporter, public nsIObserver { public: using Base = SharedSubResourceCache; NS_DECL_ISUPPORTS NS_DECL_NSIMEMORYREPORTER NS_DECL_NSIOBSERVER SharedScriptCache(); void Init(); // This has to be static because it's also called for loaders that don't have // a sheet cache (loaders that are not owned by a document). static void LoadCompleted(SharedScriptCache*, ScriptLoadData&); using Base::LoadCompleted; static void Clear(const Maybe& aChrome = Nothing(), const Maybe>& aPrincipal = Nothing(), const Maybe& aSchemelessSite = Nothing(), const Maybe& aPattern = Nothing(), const Maybe& aURL = Nothing()); static void PrepareForLastCC(); protected: ~SharedScriptCache(); }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_SharedScriptCache_h