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/. */
7 #ifndef mozilla_dom_FetchDriver_h
8 #define mozilla_dom_FetchDriver_h
10 #include "nsIChannelEventSink.h"
11 #include "nsIInterfaceRequestor.h"
12 #include "nsIStreamListener.h"
13 #include "nsIThreadRetargetableStreamListener.h"
14 #include "mozilla/ConsoleReportCollector.h"
15 #include "mozilla/dom/AbortSignal.h"
16 #include "mozilla/dom/SafeRefPtr.h"
17 #include "mozilla/dom/SerializedStackHolder.h"
18 #include "mozilla/dom/SRIMetadata.h"
19 #include "mozilla/RefPtr.h"
20 #include "mozilla/UniquePtr.h"
22 #include "mozilla/DebugOnly.h"
24 class nsIConsoleReportCollector
;
25 class nsICookieJarSettings
;
26 class nsICSPEventListener
;
28 class nsIOutputStream
;
38 class InternalRequest
;
39 class InternalResponse
;
40 class PerformanceStorage
;
43 * Provides callbacks to be called when response is available or on error.
44 * Implemenations usually resolve or reject the promise returned from fetch().
45 * The callbacks can be called synchronously or asynchronously from
48 class FetchDriverObserver
{
51 : mReporter(new ConsoleReportCollector()), mGotResponseAvailable(false) {}
53 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FetchDriverObserver
);
54 void OnResponseAvailable(InternalResponse
* aResponse
) {
55 MOZ_ASSERT(!mGotResponseAvailable
);
56 mGotResponseAvailable
= true;
57 OnResponseAvailableInternal(aResponse
);
65 virtual void OnResponseEnd(EndReason aReason
){};
67 nsIConsoleReportCollector
* GetReporter() const { return mReporter
; }
69 virtual void FlushConsoleReport() = 0;
71 // Called in OnStartRequest() to determine if the OnDataAvailable() method
72 // needs to be called. Invoking that method may generate additional main
74 virtual bool NeedOnDataAvailable() = 0;
76 // Called once when the first byte of data is received iff
77 // NeedOnDataAvailable() returned true when called in OnStartRequest().
78 virtual void OnDataAvailable() = 0;
81 virtual ~FetchDriverObserver() = default;
83 virtual void OnResponseAvailableInternal(InternalResponse
* aResponse
) = 0;
85 nsCOMPtr
<nsIConsoleReportCollector
> mReporter
;
88 bool mGotResponseAvailable
;
91 class AlternativeDataStreamListener
;
93 class FetchDriver final
: public nsIStreamListener
,
94 public nsIChannelEventSink
,
95 public nsIInterfaceRequestor
,
96 public nsIThreadRetargetableStreamListener
,
97 public AbortFollower
{
99 NS_DECL_THREADSAFE_ISUPPORTS
100 NS_DECL_NSIREQUESTOBSERVER
101 NS_DECL_NSISTREAMLISTENER
102 NS_DECL_NSICHANNELEVENTSINK
103 NS_DECL_NSIINTERFACEREQUESTOR
104 NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
106 FetchDriver(SafeRefPtr
<InternalRequest
> aRequest
, nsIPrincipal
* aPrincipal
,
107 nsILoadGroup
* aLoadGroup
, nsIEventTarget
* aMainThreadEventTarget
,
108 nsICookieJarSettings
* aCookieJarSettings
,
109 PerformanceStorage
* aPerformanceStorage
, bool aIsTrackingFetch
);
111 nsresult
Fetch(AbortSignalImpl
* aSignalImpl
, FetchDriverObserver
* aObserver
);
113 void SetDocument(Document
* aDocument
);
115 void SetCSPEventListener(nsICSPEventListener
* aCSPEventListener
);
117 void SetClientInfo(const ClientInfo
& aClientInfo
);
119 void SetController(const Maybe
<ServiceWorkerDescriptor
>& aController
);
121 void SetWorkerScript(const nsACString
& aWorkerScript
) {
122 MOZ_ASSERT(!aWorkerScript
.IsEmpty());
123 mWorkerScript
= aWorkerScript
;
126 void SetOriginStack(UniquePtr
<SerializedStackHolder
>&& aOriginStack
) {
127 mOriginStack
= std::move(aOriginStack
);
131 void RunAbortAlgorithm() override
;
134 nsCOMPtr
<nsIPrincipal
> mPrincipal
;
135 nsCOMPtr
<nsILoadGroup
> mLoadGroup
;
136 SafeRefPtr
<InternalRequest
> mRequest
;
137 RefPtr
<InternalResponse
> mResponse
;
138 nsCOMPtr
<nsIOutputStream
> mPipeOutputStream
;
139 RefPtr
<FetchDriverObserver
> mObserver
;
140 RefPtr
<Document
> mDocument
;
141 nsCOMPtr
<nsICSPEventListener
> mCSPEventListener
;
142 Maybe
<ClientInfo
> mClientInfo
;
143 Maybe
<ServiceWorkerDescriptor
> mController
;
144 nsCOMPtr
<nsIChannel
> mChannel
;
145 UniquePtr
<SRICheckDataVerifier
> mSRIDataVerifier
;
146 nsCOMPtr
<nsIEventTarget
> mMainThreadEventTarget
;
148 nsCOMPtr
<nsICookieJarSettings
> mCookieJarSettings
;
150 // This is set only when Fetch is used in workers.
151 RefPtr
<PerformanceStorage
> mPerformanceStorage
;
153 SRIMetadata mSRIMetadata
;
154 nsCString mWorkerScript
;
155 UniquePtr
<SerializedStackHolder
> mOriginStack
;
157 // This is written once in OnStartRequest on the main thread and then
158 // written/read in OnDataAvailable() on any thread. Necko guarantees
159 // that these do not overlap.
160 bool mNeedToObserveOnDataAvailable
;
162 bool mIsTrackingFetch
;
164 RefPtr
<AlternativeDataStreamListener
> mAltDataListener
;
165 bool mOnStopRequestCalled
;
167 // This flag is true when this fetch has found a matching preload and is being
168 // satisfied by a its response.
169 bool mFromPreload
= false;
170 // This flag is set in call to Abort() and spans the possible window this
171 // fetch doesn't have mChannel (to be cancelled) between reuse of the matching
172 // preload, that has already finished and dropped reference to its channel,
173 // and OnStartRequest notification. It let's us cancel the load when we get
174 // the channel in OnStartRequest.
175 bool mAborted
= false;
178 bool mResponseAvailableCalled
;
182 friend class AlternativeDataStreamListener
;
184 FetchDriver() = delete;
185 FetchDriver(const FetchDriver
&) = delete;
186 FetchDriver
& operator=(const FetchDriver
&) = delete;
189 already_AddRefed
<PreloaderBase
> FindPreload(nsIURI
* aURI
);
191 void UpdateReferrerInfoFromNewChannel(nsIChannel
* aChannel
);
193 nsresult
HttpFetch(const nsACString
& aPreferredAlternativeDataType
= ""_ns
);
194 // Returns the filtered response sent to the observer.
195 already_AddRefed
<InternalResponse
> BeginAndGetFilteredResponse(
196 InternalResponse
* aResponse
, bool aFoundOpaqueRedirect
);
197 // Utility since not all cases need to do any post processing of the filtered
199 void FailWithNetworkError(nsresult rv
);
201 void SetRequestHeaders(nsIHttpChannel
* aChannel
,
202 bool aStripRequestBodyHeader
) const;
204 void FinishOnStopRequest(AlternativeDataStreamListener
* aAltDataListener
);
208 } // namespace mozilla
210 #endif // mozilla_dom_FetchDriver_h