tor-browser

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

CacheLoadHandler.h (7876B)


      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_workers_CacheLoadHandler_h__
      8 #define mozilla_dom_workers_CacheLoadHandler_h__
      9 
     10 #include "mozilla/StaticPrefs_browser.h"
     11 #include "mozilla/dom/CacheBinding.h"
     12 #include "mozilla/dom/ChannelInfo.h"
     13 #include "mozilla/dom/Promise.h"
     14 #include "mozilla/dom/PromiseNativeHandler.h"
     15 #include "mozilla/dom/ScriptLoadHandler.h"
     16 #include "mozilla/dom/WorkerCommon.h"
     17 #include "mozilla/dom/WorkerRef.h"
     18 #include "mozilla/dom/cache/Cache.h"
     19 #include "mozilla/dom/cache/CacheStorage.h"
     20 #include "mozilla/dom/workerinternals/ScriptLoader.h"
     21 #include "nsIContentPolicy.h"
     22 #include "nsIInputStreamPump.h"
     23 #include "nsIStreamLoader.h"
     24 #include "nsStreamUtils.h"
     25 #include "nsStringFwd.h"
     26 
     27 using mozilla::dom::cache::Cache;
     28 using mozilla::dom::cache::CacheStorage;
     29 using mozilla::ipc::PrincipalInfo;
     30 
     31 namespace mozilla::dom {
     32 
     33 class WorkerLoadContext;
     34 
     35 namespace workerinternals::loader {
     36 
     37 /*
     38 * [DOMDOC] CacheLoadHandler for Workers
     39 *
     40 * A LoadHandler is a ScriptLoader helper class that reacts to an
     41 * nsIStreamLoader's events for loading JS scripts. It is primarily responsible
     42 * for decoding the stream into UTF8 or UTF16. Additionally, it takes care of
     43 * any work that needs to follow the completion of a stream. Every LoadHandler
     44 * also manages additional tasks for the type of load that it is doing.
     45 *
     46 * CacheLoadHandler is a specialized LoadHandler used by ServiceWorkers to
     47 * implement the installation model used by ServiceWorkers to support running
     48 * offline. When a ServiceWorker is installed, its main script is evaluated and
     49 * all script resources that are loaded are saved. The spec does not specify the
     50 * storage mechanism for this, but we chose to reuse the Cache API[1] mechanism
     51 * that we expose to content to also store the script and its dependencies. We
     52 * store the script resources in a special chrome namespace CacheStorage that is
     53 * not visible to content. Each distinct ServiceWorker installation gets its own
     54 * Cache keyed by a randomly-generated UUID.
     55 *
     56 * In terms of specification, this class implements step 4 of
     57 * https://w3c.github.io/ServiceWorker/#importscripts
     58 *
     59 * Relationship to NetworkLoadHandler
     60 *
     61 * During ServiceWorker installation, the CacheLoadHandler falls back on the
     62 * NetworkLoadHandler by calling `mLoader->LoadScript(...)`. If a script has not
     63 * been seen before, then we will fall back on loading from the network.
     64 * However, if the ServiceWorker is already installed, an error will be
     65 * generated and the ServiceWorker will fail to load, per spec.
     66 *
     67 * CacheLoadHandler does not persist some pieces of information, such as the
     68 * sourceMapUrl. Also, the DOM Cache API storage does not yet support alternate
     69 * data streams for JS Bytecode or WASM caching; this is tracked by Bug 1336199.
     70 *
     71 * [1]: https://developer.mozilla.org/en-US/docs/Web/API/caches
     72 *
     73 */
     74 
     75 class CacheLoadHandler final : public PromiseNativeHandler,
     76                               public nsIStreamLoaderObserver {
     77 public:
     78  NS_DECL_ISUPPORTS
     79  NS_DECL_NSISTREAMLOADEROBSERVER
     80 
     81  CacheLoadHandler(ThreadSafeWorkerRef* aWorkerRef,
     82                   ThreadSafeRequestHandle* aRequestHandle,
     83                   bool aIsWorkerScript,
     84                   bool aOnlyExistingCachedResourcesAllowed,
     85                   WorkerScriptLoader* aLoader);
     86 
     87  void Fail(nsresult aRv);
     88 
     89  void Load(Cache* aCache);
     90 
     91  virtual void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
     92                                ErrorResult& aRv) override;
     93 
     94  virtual void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
     95                                ErrorResult& aRv) override;
     96 
     97 private:
     98  ~CacheLoadHandler() { AssertIsOnMainThread(); }
     99 
    100  nsresult DataReceivedFromCache(const uint8_t* aString, uint32_t aStringLen,
    101                                 const mozilla::dom::ChannelInfo& aChannelInfo,
    102                                 UniquePtr<PrincipalInfo> aPrincipalInfo,
    103                                 const nsACString& aCSPHeaderValue,
    104                                 const nsACString& aCSPReportOnlyHeaderValue,
    105                                 const nsACString& aReferrerPolicyHeaderValue);
    106  nsresult DataReceived();
    107 
    108  RefPtr<ThreadSafeRequestHandle> mRequestHandle;
    109  const RefPtr<WorkerScriptLoader> mLoader;
    110  RefPtr<ThreadSafeWorkerRef> mWorkerRef;
    111  const bool mIsWorkerScript;
    112  bool mFailed;
    113  bool mOnlyExistingCachedResourcesAllowed;
    114  nsCOMPtr<nsIInputStreamPump> mPump;
    115  nsCOMPtr<nsIURI> mBaseURI;
    116  mozilla::dom::ChannelInfo mChannelInfo;
    117  UniquePtr<PrincipalInfo> mPrincipalInfo;
    118  UniquePtr<ScriptDecoder> mDecoder;
    119  nsCString mCSPHeaderValue;
    120  nsCString mCSPReportOnlyHeaderValue;
    121  nsCString mReferrerPolicyHeaderValue;
    122  nsCOMPtr<nsISerialEventTarget> mMainThreadEventTarget;
    123 };
    124 
    125 /*
    126 * CacheCreator
    127 *
    128 * The CacheCreator is responsible for maintaining a CacheStorage for the
    129 * purposes of caching ServiceWorkers (see comment on CacheLoadHandler). In
    130 * addition, it tracks all CacheLoadHandlers and is used for cleanup once
    131 * loading has finished.
    132 *
    133 */
    134 
    135 class CacheCreator final : public PromiseNativeHandler {
    136 public:
    137  NS_DECL_ISUPPORTS
    138 
    139  explicit CacheCreator(WorkerPrivate* aWorkerPrivate);
    140 
    141  void AddLoader(MovingNotNull<RefPtr<CacheLoadHandler>> aLoader) {
    142    AssertIsOnMainThread();
    143    MOZ_ASSERT(!mCacheStorage);
    144    mLoaders.AppendElement(std::move(aLoader));
    145  }
    146 
    147  virtual void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
    148                                ErrorResult& aRv) override;
    149 
    150  virtual void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
    151                                ErrorResult& aRv) override;
    152 
    153  // Try to load from cache with aPrincipal used for cache access.
    154  nsresult Load(nsIPrincipal* aPrincipal);
    155 
    156  Cache* Cache_() const {
    157    AssertIsOnMainThread();
    158    MOZ_ASSERT(mCache);
    159    return mCache;
    160  }
    161 
    162  nsIGlobalObject* Global() const {
    163    AssertIsOnMainThread();
    164    MOZ_ASSERT(mSandboxGlobalObject);
    165    return mSandboxGlobalObject;
    166  }
    167 
    168  void DeleteCache(nsresult aReason);
    169 
    170 private:
    171  ~CacheCreator() = default;
    172 
    173  nsresult CreateCacheStorage(nsIPrincipal* aPrincipal);
    174 
    175  void FailLoaders(nsresult aRv);
    176 
    177  RefPtr<Cache> mCache;
    178  RefPtr<CacheStorage> mCacheStorage;
    179  nsCOMPtr<nsIGlobalObject> mSandboxGlobalObject;
    180  nsTArray<NotNull<RefPtr<CacheLoadHandler>>> mLoaders;
    181 
    182  nsString mCacheName;
    183  OriginAttributes mOriginAttributes;
    184 };
    185 
    186 /*
    187 * CachePromiseHandler
    188 *
    189 * This promise handler is used to track if a ServiceWorker has been written to
    190 * Cache. It is responsible for tracking the state of the ServiceWorker being
    191 * cached. It also handles cancelling caching of a ServiceWorker if loading is
    192 * interrupted. It is initialized by the NetworkLoadHandler as part of the first
    193 * load of a ServiceWorker.
    194 *
    195 */
    196 class CachePromiseHandler final : public PromiseNativeHandler {
    197 public:
    198  NS_DECL_ISUPPORTS
    199 
    200  CachePromiseHandler(WorkerScriptLoader* aLoader,
    201                      ThreadSafeRequestHandle* aRequestHandle);
    202 
    203  virtual void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
    204                                ErrorResult& aRv) override;
    205 
    206  virtual void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
    207                                ErrorResult& aRv) override;
    208 
    209 private:
    210  ~CachePromiseHandler() { AssertIsOnMainThread(); }
    211 
    212  RefPtr<WorkerScriptLoader> mLoader;
    213  RefPtr<ThreadSafeRequestHandle> mRequestHandle;
    214 };
    215 
    216 }  // namespace workerinternals::loader
    217 }  // namespace mozilla::dom
    218 
    219 #endif /* mozilla_dom_workers_CacheLoadHandler_h__ */