summaryrefslogtreecommitdiffstats
path: root/uriloader/preload/PreloadService.h
blob: 79f5e7b6d137715012f6e085d8adacaac8f0f02d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* -*- 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 PreloadService_h__
#define PreloadService_h__

#include "nsIContentPolicy.h"
#include "nsIURI.h"
#include "nsRefPtrHashtable.h"
#include "mozilla/PreloadHashKey.h"

class nsINode;

namespace mozilla {

class PreloaderBase;

namespace dom {

class HTMLLinkElement;
class Document;
enum class ReferrerPolicy : uint8_t;

}  // namespace dom

/**
 * Intended to scope preloads
 * (https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/preload)
 * and speculative loads initiated by the parser under one roof.  This class
 * is intended to be a member of dom::Document. Provides registration of
 * speculative loads via a `key` which is defined to consist of the URL,
 * resource type, and resource-specific attributes that are further
 * distinguishing loads with otherwise same type and url.
 */
class PreloadService {
 public:
  explicit PreloadService(dom::Document*);
  ~PreloadService();

  // Called by resource loaders to register a running resource load.  This is
  // called for a speculative load when it's started the first time, being it
  // either regular speculative load or a preload.
  //
  // Returns false and does nothing if a preload is already registered under
  // this key, true otherwise.
  bool RegisterPreload(const PreloadHashKey& aKey, PreloaderBase* aPreload);

  // Called when the load is about to be cancelled.  Exact behavior is to be
  // determined yet.
  void DeregisterPreload(const PreloadHashKey& aKey);

  // Called when the scope is to go away.
  void ClearAllPreloads();

  // True when there is a preload registered under the key.
  bool PreloadExists(const PreloadHashKey& aKey);

  // Returns an existing preload under the key or null, when there is none
  // registered under the key.
  already_AddRefed<PreloaderBase> LookupPreload(
      const PreloadHashKey& aKey) const;

  void SetSpeculationBase(nsIURI* aURI) { mSpeculationBaseURI = aURI; }
  already_AddRefed<nsIURI> GetPreloadURI(const nsAString& aURL);

  already_AddRefed<PreloaderBase> PreloadLinkElement(
      dom::HTMLLinkElement* aLink, nsContentPolicyType aPolicyType);

  // a non-zero aEarlyHintPreloaderId tells this service that a preload for this
  // link was started by the EarlyHintPreloader and the preloaders should
  // connect back by setting earlyHintPreloaderId in nsIChannelInternal before
  // AsyncOpen.
  void PreloadLinkHeader(nsIURI* aURI, const nsAString& aURL,
                         nsContentPolicyType aPolicyType, const nsAString& aAs,
                         const nsAString& aType, const nsAString& aNonce,
                         const nsAString& aIntegrity, const nsAString& aSrcset,
                         const nsAString& aSizes, const nsAString& aCORS,
                         const nsAString& aReferrerPolicy,
                         uint64_t aEarlyHintPreloaderId,
                         const nsAString& aFetchPriority);

  void PreloadScript(nsIURI* aURI, const nsAString& aType,
                     const nsAString& aCharset, const nsAString& aCrossOrigin,
                     const nsAString& aReferrerPolicy, const nsAString& aNonce,
                     const nsAString& aFetchPriority,
                     const nsAString& aIntegrity, bool aScriptFromHead,
                     uint64_t aEarlyHintPreloaderId);

  void PreloadImage(nsIURI* aURI, const nsAString& aCrossOrigin,
                    const nsAString& aImageReferrerPolicy, bool aIsImgSet,
                    uint64_t aEarlyHintPreloaderId,
                    const nsAString& aFetchPriority);

  void PreloadFont(nsIURI* aURI, const nsAString& aCrossOrigin,
                   const nsAString& aReferrerPolicy,
                   uint64_t aEarlyHintPreloaderId,
                   const nsAString& aFetchPriority);

  void PreloadFetch(nsIURI* aURI, const nsAString& aCrossOrigin,
                    const nsAString& aReferrerPolicy,
                    uint64_t aEarlyHintPreloaderId,
                    const nsAString& aFetchPriority);

  static void NotifyNodeEvent(nsINode* aNode, bool aSuccess);

  void SetEarlyHintUsed() { mEarlyHintUsed = true; }
  bool GetEarlyHintUsed() const { return mEarlyHintUsed; }

 private:
  dom::ReferrerPolicy PreloadReferrerPolicy(const nsAString& aReferrerPolicy);
  nsIURI* BaseURIForPreload();

  struct PreloadOrCoalesceResult {
    RefPtr<PreloaderBase> mPreloader;
    bool mAlreadyComplete;
  };

  PreloadOrCoalesceResult PreloadOrCoalesce(
      nsIURI* aURI, const nsAString& aURL, nsContentPolicyType aPolicyType,
      const nsAString& aAs, const nsAString& aType, const nsAString& aCharset,
      const nsAString& aSrcset, const nsAString& aSizes,
      const nsAString& aNonce, const nsAString& aIntegrity,
      const nsAString& aCORS, const nsAString& aReferrerPolicy,
      const nsAString& aFetchPriority, bool aFromHeader,
      uint64_t aEarlyHintPreloaderId);

 private:
  nsRefPtrHashtable<PreloadHashKey, PreloaderBase> mPreloads;

  // Raw pointer only, we are intended to be a direct member of dom::Document
  dom::Document* mDocument;

  // Set by `nsHtml5TreeOpExecutor::SetSpeculationBase`.
  nsCOMPtr<nsIURI> mSpeculationBaseURI;

  bool mEarlyHintUsed = false;
};

}  // namespace mozilla

#endif