summaryrefslogtreecommitdiffstats
path: root/uriloader/preload/FetchPreloader.h
blob: 24c3babd8961a6091e12d9a4a7da4c0e32887546 (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
/* -*- 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 FetchPreloader_h_
#define FetchPreloader_h_

#include "mozilla/PreloaderBase.h"
#include "mozilla/Variant.h"
#include "nsCOMPtr.h"
#include "nsIAsyncOutputStream.h"
#include "nsIAsyncInputStream.h"
#include "nsIContentPolicy.h"
#include "nsIStreamListener.h"

class nsIChannel;
class nsILoadGroup;
class nsIInterfaceRequestor;

namespace mozilla {

namespace dom {
enum class ReferrerPolicy : uint8_t;
}

class FetchPreloader : public PreloaderBase, public nsIStreamListener {
  NS_DECL_ISUPPORTS
  NS_DECL_NSIREQUESTOBSERVER
  NS_DECL_NSISTREAMLISTENER

  FetchPreloader();

  // @param aSupportsPriorityValue see <nsISupportsPriority.idl>.
  nsresult OpenChannel(const PreloadHashKey& aKey, nsIURI* aURI,
                       const CORSMode aCORSMode,
                       const dom::ReferrerPolicy& aReferrerPolicy,
                       dom::Document* aDocument, uint64_t aEarlyHintPreloaderId,
                       int32_t aSupportsPriorityValue);

  // PreloaderBase
  nsresult AsyncConsume(nsIStreamListener* aListener) override;

  static void PrioritizeAsPreload(nsIChannel* aChannel);

 protected:
  explicit FetchPreloader(nsContentPolicyType aContentPolicyType);
  virtual ~FetchPreloader() = default;

  // Create and setup the channel with necessary security properties and
  // the nsISupportsPriority value. This is overridable by
  // subclasses to allow different initial conditions.
  //
  // @param aSupportsPriorityValue see <nsISupportsPriority.idl>.
  virtual nsresult CreateChannel(
      nsIChannel** aChannel, nsIURI* aURI, const CORSMode aCORSMode,
      const dom::ReferrerPolicy& aReferrerPolicy, dom::Document* aDocument,
      nsILoadGroup* aLoadGroup, nsIInterfaceRequestor* aCallbacks,
      uint64_t aEarlyHintPreloaderId, int32_t aSupportsPriorityValue);

 private:
  // @param aSupportsPriorityValue see <nsISupportsPriority.idl>.
  static void AdjustPriority(nsIChannel* aChannel,
                             int32_t aSupportsPriorityValue);

  nsresult CheckContentPolicy(nsIURI* aURI, dom::Document* aDocument);

  class Cache final : public nsIStreamListener {
    NS_DECL_ISUPPORTS
    NS_DECL_NSIREQUESTOBSERVER
    NS_DECL_NSISTREAMLISTENER

    void AsyncConsume(nsIStreamListener* aListener);
    void Consume(nsCOMPtr<nsIStreamListener> aListener);

   private:
    virtual ~Cache() = default;

    struct StartRequest {};
    struct DataAvailable {
      nsCString mData;
    };
    struct StopRequest {
      nsresult mStatus;
    };

    typedef Variant<StartRequest, DataAvailable, StopRequest> Call;
    nsCOMPtr<nsIRequest> mRequest;
    nsCOMPtr<nsIStreamListener> mFinalListener;
    nsTArray<Call> mCalls;
  };

  // The listener passed to AsyncConsume in case we haven't started getting the
  // data from the channel yet.
  nsCOMPtr<nsIStreamListener> mConsumeListener;

  // Returned by AsyncConsume when a failure.  This remembers the result of
  // opening the channel and prevents duplicate consumation.
  nsresult mAsyncConsumeResult = NS_ERROR_NOT_AVAILABLE;

  // The CP type to check against.  Derived classes have to override call to CSP
  // constructor of this class.
  nsContentPolicyType mContentPolicyType;
};

}  // namespace mozilla

#endif