tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SharedScriptCache.h (8941B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_dom_SharedScriptCache_h
      8 #define mozilla_dom_SharedScriptCache_h
      9 
     10 #include "PLDHashTable.h"                    // PLDHashEntryHdr
     11 #include "js/loader/LoadedScript.h"          // JS::loader::LoadedScript
     12 #include "js/loader/ScriptFetchOptions.h"    // JS::loader::ScriptFetchOptions
     13 #include "js/loader/ScriptKind.h"            // JS::loader::ScriptKind
     14 #include "js/loader/ScriptLoadRequest.h"     // JS::loader::ScriptLoadRequest
     15 #include "mozilla/CORSMode.h"                // mozilla::CORSMode
     16 #include "mozilla/MemoryReporting.h"         // MallocSizeOf
     17 #include "mozilla/Mutex.h"                   // Mutex, GUARDED_BY, MutexAutoLock
     18 #include "mozilla/RefPtr.h"                  // RefPtr
     19 #include "mozilla/SharedSubResourceCache.h"  // SharedSubResourceCache, SharedSubResourceCacheLoadingValueBase, SubResourceNetworkMetadataHolder
     20 #include "mozilla/ThreadSafety.h"            // MOZ_GUARDED_BY
     21 #include "mozilla/WeakPtr.h"                 // SupportsWeakPtr
     22 #include "mozilla/dom/CacheExpirationTime.h"  // CacheExpirationTime
     23 #include "mozilla/dom/SRIMetadata.h"          // mozilla::dom::SRIMetadata
     24 #include "nsIMemoryReporter.h"  // nsIMemoryReporter, NS_DECL_NSIMEMORYREPORTER
     25 #include "nsIPrincipal.h"       // nsIPrincipal
     26 #include "nsISupports.h"        // nsISupports, NS_DECL_ISUPPORTS
     27 #include "nsStringFwd.h"        // nsACString
     28 
     29 namespace mozilla {
     30 namespace dom {
     31 
     32 class ScriptLoader;
     33 class ScriptLoadData;
     34 
     35 class ScriptHashKey : public PLDHashEntryHdr {
     36 public:
     37  using KeyType = const ScriptHashKey&;
     38  using KeyTypePointer = const ScriptHashKey*;
     39 
     40  explicit ScriptHashKey(const ScriptHashKey& aKey)
     41      : PLDHashEntryHdr(),
     42        mURI(aKey.mURI),
     43        mPartitionPrincipal(aKey.mPartitionPrincipal),
     44        mLoaderPrincipal(aKey.mLoaderPrincipal),
     45        mKind(aKey.mKind),
     46        mCORSMode(aKey.mCORSMode),
     47        mReferrerPolicy(aKey.mReferrerPolicy),
     48        mSRIMetadata(aKey.mSRIMetadata),
     49        mNonce(aKey.mNonce),
     50        mHintCharset(aKey.mHintCharset) {
     51    MOZ_COUNT_CTOR(ScriptHashKey);
     52  }
     53 
     54  explicit ScriptHashKey(const ScriptHashKey* aKey) : ScriptHashKey(*aKey) {}
     55 
     56  ScriptHashKey(ScriptHashKey&& aKey)
     57      : PLDHashEntryHdr(),
     58        mURI(std::move(aKey.mURI)),
     59        mPartitionPrincipal(std::move(aKey.mPartitionPrincipal)),
     60        mLoaderPrincipal(std::move(aKey.mLoaderPrincipal)),
     61        mKind(std::move(aKey.mKind)),
     62        mCORSMode(std::move(aKey.mCORSMode)),
     63        mReferrerPolicy(std::move(aKey.mReferrerPolicy)),
     64        mSRIMetadata(std::move(aKey.mSRIMetadata)),
     65        mNonce(std::move(aKey.mNonce)),
     66        mHintCharset(std::move(aKey.mHintCharset)) {
     67    MOZ_COUNT_CTOR(ScriptHashKey);
     68  }
     69 
     70  ScriptHashKey(ScriptLoader* aLoader,
     71                const JS::loader::ScriptLoadRequest* aRequest,
     72                const JS::loader::LoadedScript* aLoadedScript);
     73  ScriptHashKey(ScriptLoader* aLoader,
     74                const JS::loader::ScriptLoadRequest* aRequest,
     75                mozilla::dom::ReferrerPolicy aReferrerPolicy,
     76                const JS::loader::ScriptFetchOptions* aFetchOptions,
     77                const nsCOMPtr<nsIURI> aURI);
     78  explicit ScriptHashKey(const ScriptLoadData& aLoadData);
     79 
     80  MOZ_COUNTED_DTOR(ScriptHashKey)
     81 
     82  const ScriptHashKey& GetKey() const { return *this; }
     83  const ScriptHashKey* GetKeyPointer() const { return this; }
     84 
     85  bool KeyEquals(const ScriptHashKey* aKey) const { return KeyEquals(*aKey); }
     86 
     87  bool KeyEquals(const ScriptHashKey&) const;
     88 
     89  static const ScriptHashKey* KeyToPointer(const ScriptHashKey& aKey) {
     90    return &aKey;
     91  }
     92  static PLDHashNumber HashKey(const ScriptHashKey* aKey) {
     93    return nsURIHashKey::HashKey(aKey->mURI);
     94  }
     95 
     96  nsIPrincipal* LoaderPrincipal() const { return mLoaderPrincipal; }
     97  nsIPrincipal* PartitionPrincipal() const { return mPartitionPrincipal; }
     98 
     99  nsIURI* URI() const { return mURI; }
    100 
    101  enum { ALLOW_MEMMOVE = true };
    102 
    103 protected:
    104  // Order the fields from the most important one as much as possible, while
    105  // packing them, in order to use the same order between the definition and
    106  // the KeyEquals implementation.
    107 
    108  // The script's URI.  This should distinguish the cache entry in most case.
    109  const nsCOMPtr<nsIURI> mURI;
    110 
    111  // If single content process has multiple principals, mPartitionPrincipal
    112  // should distinguish them.
    113  const nsCOMPtr<nsIPrincipal> mPartitionPrincipal;
    114 
    115  // NOTE: mLoaderPrincipal is only for SharedSubResourceCache logic,
    116  //       and not part of KeyEquals.
    117  const nsCOMPtr<nsIPrincipal> mLoaderPrincipal;
    118 
    119  // Other fields should be unique per each script in general.
    120  const JS::loader::ScriptKind mKind;
    121  const CORSMode mCORSMode;
    122  const mozilla::dom::ReferrerPolicy mReferrerPolicy;
    123 
    124  const SRIMetadata mSRIMetadata;
    125  const nsString mNonce;
    126 
    127  // charset attribute for classic script.
    128  // module always use UTF-8.
    129  nsString mHintCharset;
    130 };
    131 
    132 class ScriptLoadData final
    133    : public SupportsWeakPtr,
    134      public nsISupports,
    135      public SharedSubResourceCacheLoadingValueBase<ScriptLoadData> {
    136 protected:
    137  ~ScriptLoadData() {}
    138 
    139 public:
    140  ScriptLoadData(ScriptLoader* aLoader, JS::loader::ScriptLoadRequest* aRequest,
    141                 JS::loader::LoadedScript* aLoadedScript);
    142 
    143  NS_DECL_ISUPPORTS
    144 
    145  // Only completed loads are used for the cache.
    146  bool IsLoading() const override { return false; }
    147  bool IsCancelled() const override { return false; }
    148  bool IsSyncLoad() const override { return true; }
    149 
    150  SubResourceNetworkMetadataHolder* GetNetworkMetadata() const override {
    151    return mNetworkMetadata.get();
    152  }
    153 
    154  void StartLoading() override {}
    155  void SetLoadCompleted() override {}
    156  void OnCoalescedTo(const ScriptLoadData& aExistingLoad) override {}
    157  void Cancel() override {}
    158 
    159  void DidCancelLoad() {}
    160 
    161  bool ShouldDefer() const { return false; }
    162 
    163  JS::loader::LoadedScript* ValueForCache() const {
    164    return mLoadedScript.get();
    165  }
    166 
    167  const CacheExpirationTime& ExpirationTime() const { return mExpirationTime; }
    168 
    169  ScriptLoader& Loader() { return *mLoader; }
    170 
    171  const ScriptHashKey& CacheKey() const { return mKey; }
    172 
    173 private:
    174  CacheExpirationTime mExpirationTime = CacheExpirationTime::Never();
    175  ScriptLoader* mLoader;
    176  ScriptHashKey mKey;
    177  RefPtr<JS::loader::LoadedScript> mLoadedScript;
    178  RefPtr<SubResourceNetworkMetadataHolder> mNetworkMetadata;
    179 };
    180 
    181 struct SharedScriptCacheTraits {
    182  using Loader = ScriptLoader;
    183  using Key = ScriptHashKey;
    184  using Value = JS::loader::LoadedScript;
    185  using LoadingValue = ScriptLoadData;
    186 
    187  static ScriptHashKey KeyFromLoadingValue(const LoadingValue& aValue) {
    188    return ScriptHashKey(aValue);
    189  }
    190 };
    191 
    192 class SharedScriptCache final
    193    : public SharedSubResourceCache<SharedScriptCacheTraits, SharedScriptCache>,
    194      public nsIMemoryReporter {
    195 public:
    196  using Base =
    197      SharedSubResourceCache<SharedScriptCacheTraits, SharedScriptCache>;
    198 
    199  NS_DECL_ISUPPORTS
    200  NS_DECL_NSIMEMORYREPORTER
    201 
    202  SharedScriptCache();
    203  void Init();
    204 
    205  bool MaybeScheduleUpdateDiskCache();
    206  void UpdateDiskCache();
    207 
    208  void EncodeAndCompress();
    209  void SaveToDiskCache();
    210 
    211  void InvalidateInProcess();
    212 
    213  // This has to be static because it's also called for loaders that don't have
    214  // a sheet cache (loaders that are not owned by a document).
    215  static void LoadCompleted(SharedScriptCache*, ScriptLoadData&);
    216  using Base::LoadCompleted;
    217  static void Clear(const Maybe<bool>& aChrome = Nothing(),
    218                    const Maybe<nsCOMPtr<nsIPrincipal>>& aPrincipal = Nothing(),
    219                    const Maybe<nsCString>& aSchemelessSite = Nothing(),
    220                    const Maybe<OriginAttributesPattern>& aPattern = Nothing(),
    221                    const Maybe<nsCString>& aURL = Nothing());
    222 
    223  static void Invalidate();
    224 
    225  static void PrepareForLastCC();
    226 
    227 protected:
    228  ~SharedScriptCache();
    229 
    230 private:
    231  class EncodeItem {
    232   public:
    233    EncodeItem(JS::Stencil* aStencil, JS::TranscodeBuffer&& aSRI,
    234               JS::loader::LoadedScript* aLoadedScript)
    235        : mStencil(aStencil),
    236          mSRI(std::move(aSRI)),
    237          mLoadedScript(aLoadedScript) {}
    238 
    239    // These fields can be touched from multiple threads.
    240    RefPtr<JS::Stencil> mStencil;
    241    JS::TranscodeBuffer mSRI;
    242    Vector<uint8_t> mCompressed;
    243 
    244    // This can be dereferenced only from the main thread.
    245    // Reading the pointer itself is allowed also off main thread.
    246    RefPtr<JS::loader::LoadedScript> mLoadedScript;
    247  };
    248 
    249  Mutex mEncodeMutex{"SharedScriptCache::mEncodeMutex"};
    250  Vector<EncodeItem> mEncodeItems MOZ_GUARDED_BY(mEncodeMutex);
    251 };
    252 
    253 }  // namespace dom
    254 }  // namespace mozilla
    255 
    256 #endif  // mozilla_dom_SharedScriptCache_h