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 "nsINetworkInterceptController.h"
13 #include "nsIStreamListener.h"
14 #include "nsIThreadRetargetableStreamListener.h"
15 #include "mozilla/ConsoleReportCollector.h"
16 #include "mozilla/dom/AbortSignal.h"
17 #include "mozilla/dom/SafeRefPtr.h"
18 #include "mozilla/dom/SerializedStackHolder.h"
19 #include "mozilla/dom/SRIMetadata.h"
20 #include "mozilla/RefPtr.h"
21 #include "mozilla/UniquePtr.h"
23 #include "mozilla/DebugOnly.h"
25 class nsIConsoleReportCollector
;
26 class nsICookieJarSettings
;
27 class nsICSPEventListener
;
29 class nsIOutputStream
;
39 class InternalRequest
;
40 class InternalResponse
;
41 class PerformanceStorage
;
42 class PerformanceTimingData
;
45 * Provides callbacks to be called when response is available or on error.
46 * Implemenations usually resolve or reject the promise returned from fetch().
47 * The callbacks can be called synchronously or asynchronously from
50 class FetchDriverObserver
{
53 : mReporter(new ConsoleReportCollector()), mGotResponseAvailable(false) {}
55 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FetchDriverObserver
);
56 void OnResponseAvailable(SafeRefPtr
<InternalResponse
> aResponse
);
63 virtual void OnResponseEnd(EndReason aReason
,
64 JS::Handle
<JS::Value
> aReasonDetails
) {};
66 nsIConsoleReportCollector
* GetReporter() const { return mReporter
; }
68 virtual void FlushConsoleReport() = 0;
70 // Called in OnStartRequest() to determine if the OnDataAvailable() method
71 // needs to be called. Invoking that method may generate additional main
73 virtual bool NeedOnDataAvailable() = 0;
75 // Called once when the first byte of data is received iff
76 // NeedOnDataAvailable() returned true when called in OnStartRequest().
77 virtual void OnDataAvailable() = 0;
79 virtual void OnReportPerformanceTiming() {}
81 virtual void OnNotifyNetworkMonitorAlternateStack(uint64_t aChannelID
) {}
84 virtual ~FetchDriverObserver() = default;
86 virtual void OnResponseAvailableInternal(
87 SafeRefPtr
<InternalResponse
> aResponse
) = 0;
89 nsCOMPtr
<nsIConsoleReportCollector
> mReporter
;
92 bool mGotResponseAvailable
;
95 class AlternativeDataStreamListener
;
97 class FetchDriver final
: public nsIChannelEventSink
,
98 public nsIInterfaceRequestor
,
99 public nsINetworkInterceptController
,
100 public nsIThreadRetargetableStreamListener
,
101 public AbortFollower
{
103 NS_DECL_THREADSAFE_ISUPPORTS
104 NS_DECL_NSIREQUESTOBSERVER
105 NS_DECL_NSISTREAMLISTENER
106 NS_DECL_NSICHANNELEVENTSINK
107 NS_DECL_NSIINTERFACEREQUESTOR
108 NS_DECL_NSINETWORKINTERCEPTCONTROLLER
109 NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
111 FetchDriver(SafeRefPtr
<InternalRequest
> aRequest
, nsIPrincipal
* aPrincipal
,
112 nsILoadGroup
* aLoadGroup
, nsIEventTarget
* aMainThreadEventTarget
,
113 nsICookieJarSettings
* aCookieJarSettings
,
114 PerformanceStorage
* aPerformanceStorage
, bool aIsTrackingFetch
);
116 nsresult
Fetch(AbortSignalImpl
* aSignalImpl
, FetchDriverObserver
* aObserver
);
118 void SetDocument(Document
* aDocument
);
120 void SetCSPEventListener(nsICSPEventListener
* aCSPEventListener
);
122 void SetClientInfo(const ClientInfo
& aClientInfo
);
124 void SetController(const Maybe
<ServiceWorkerDescriptor
>& aController
);
126 void SetWorkerScript(const nsACString
& aWorkerScript
) {
127 MOZ_ASSERT(!aWorkerScript
.IsEmpty());
128 mWorkerScript
= aWorkerScript
;
131 void SetOriginStack(UniquePtr
<SerializedStackHolder
>&& aOriginStack
) {
132 mOriginStack
= std::move(aOriginStack
);
135 PerformanceTimingData
* GetPerformanceTimingData(nsAString
& aInitiatorType
,
136 nsAString
& aEntryName
);
139 void RunAbortAlgorithm() override
;
140 void FetchDriverAbortActions(AbortSignalImpl
* aSignalImpl
);
142 void EnableNetworkInterceptControl();
144 void SetAssociatedBrowsingContextID(uint64_t aID
) {
145 mAssociatedBrowsingContextID
= aID
;
148 void SetIsThirdPartyWorker(const Maybe
<bool> aIsThirdPartyWorker
) {
149 mIsThirdPartyWorker
= aIsThirdPartyWorker
;
153 nsCOMPtr
<nsIPrincipal
> mPrincipal
;
154 nsCOMPtr
<nsILoadGroup
> mLoadGroup
;
155 SafeRefPtr
<InternalRequest
> mRequest
;
156 SafeRefPtr
<InternalResponse
> mResponse
;
157 nsCOMPtr
<nsIOutputStream
> mPipeOutputStream
;
158 // Access to mObserver can be racy from OnDataAvailable and
159 // FetchAbortActions. This must not be modified
160 // in either of these functions.
161 RefPtr
<FetchDriverObserver
> mObserver
;
162 RefPtr
<Document
> mDocument
;
163 nsCOMPtr
<nsICSPEventListener
> mCSPEventListener
;
164 Maybe
<ClientInfo
> mClientInfo
;
165 Maybe
<ServiceWorkerDescriptor
> mController
;
166 nsCOMPtr
<nsIChannel
> mChannel
;
167 UniquePtr
<SRICheckDataVerifier
> mSRIDataVerifier
;
168 nsCOMPtr
<nsIEventTarget
> mMainThreadEventTarget
;
170 nsCOMPtr
<nsICookieJarSettings
> mCookieJarSettings
;
172 // This is set only when Fetch is used in workers.
173 RefPtr
<PerformanceStorage
> mPerformanceStorage
;
175 SRIMetadata mSRIMetadata
;
176 nsCString mWorkerScript
;
177 UniquePtr
<SerializedStackHolder
> mOriginStack
;
179 // This is written once in OnStartRequest on the main thread and then
180 // written/read in OnDataAvailable() on any thread. Necko guarantees
181 // that these do not overlap.
182 bool mNeedToObserveOnDataAvailable
;
184 bool mIsTrackingFetch
;
186 // Indicates whether the fetch request is from a third-party worker. Nothing
187 // if the fetch request is not from a worker.
188 Maybe
<bool> mIsThirdPartyWorker
;
190 RefPtr
<AlternativeDataStreamListener
> mAltDataListener
;
191 bool mOnStopRequestCalled
;
193 // This flag is true when this fetch has found a matching preload and is being
194 // satisfied by a its response.
195 bool mFromPreload
= false;
196 // This flag is set in call to Abort() and spans the possible window this
197 // fetch doesn't have mChannel (to be cancelled) between reuse of the matching
198 // preload, that has already finished and dropped reference to its channel,
199 // and OnStartRequest notification. It let's us cancel the load when we get
200 // the channel in OnStartRequest.
201 bool mAborted
= false;
204 bool mResponseAvailableCalled
;
207 nsCOMPtr
<nsINetworkInterceptController
> mInterceptController
;
209 uint64_t mAssociatedBrowsingContextID
{0};
211 friend class AlternativeDataStreamListener
;
213 FetchDriver() = delete;
214 FetchDriver(const FetchDriver
&) = delete;
215 FetchDriver
& operator=(const FetchDriver
&) = delete;
218 already_AddRefed
<PreloaderBase
> FindPreload(nsIURI
* aURI
);
220 void UpdateReferrerInfoFromNewChannel(nsIChannel
* aChannel
);
222 nsresult
HttpFetch(const nsACString
& aPreferredAlternativeDataType
= ""_ns
);
223 // Returns the filtered response sent to the observer.
224 SafeRefPtr
<InternalResponse
> BeginAndGetFilteredResponse(
225 SafeRefPtr
<InternalResponse
> aResponse
, bool aFoundOpaqueRedirect
);
226 // Utility since not all cases need to do any post processing of the filtered
228 void FailWithNetworkError(nsresult rv
);
230 void SetRequestHeaders(nsIHttpChannel
* aChannel
, bool aStripRequestBodyHeader
,
231 bool aStripAuthHeader
) const;
233 void FinishOnStopRequest(AlternativeDataStreamListener
* aAltDataListener
);
237 } // namespace mozilla
239 #endif // mozilla_dom_FetchDriver_h