FetchDriver.h (8353B)
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_FetchDriver_h 8 #define mozilla_dom_FetchDriver_h 9 10 #include "mozilla/ConsoleReportCollector.h" 11 #include "mozilla/Mutex.h" 12 #include "mozilla/RefPtr.h" 13 #include "mozilla/UniquePtr.h" 14 #include "mozilla/dom/AbortSignal.h" 15 #include "mozilla/dom/SRIMetadata.h" 16 #include "mozilla/dom/SafeRefPtr.h" 17 #include "mozilla/dom/SerializedStackHolder.h" 18 #include "nsIChannelEventSink.h" 19 #include "nsIClassifiedChannel.h" 20 #include "nsIInterfaceRequestor.h" 21 #include "nsINetworkInterceptController.h" 22 #include "nsIStreamListener.h" 23 #include "nsIThreadRetargetableStreamListener.h" 24 25 class nsIConsoleReportCollector; 26 class nsICookieJarSettings; 27 class nsICSPEventListener; 28 class nsIEventTarget; 29 class nsIOutputStream; 30 class nsILoadGroup; 31 class nsIPrincipal; 32 33 namespace mozilla { 34 class PreloaderBase; 35 36 namespace dom { 37 38 class Document; 39 class InternalRequest; 40 class InternalResponse; 41 class PerformanceStorage; 42 class PerformanceTimingData; 43 44 /** 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 48 * FetchDriver::Fetch. 49 */ 50 class FetchDriverObserver { 51 public: 52 FetchDriverObserver() 53 : mReporter(new ConsoleReportCollector()), mGotResponseAvailable(false) {} 54 55 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FetchDriverObserver); 56 void OnResponseAvailable(SafeRefPtr<InternalResponse> aResponse); 57 58 enum EndReason { 59 eAborted, 60 eByNetworking, 61 }; 62 63 virtual void OnResponseEnd(EndReason aReason, 64 JS::Handle<JS::Value> aReasonDetails) {}; 65 66 nsIConsoleReportCollector* GetReporter() const { return mReporter; } 67 68 virtual void FlushConsoleReport() = 0; 69 70 // Called in OnStartRequest() to determine if the OnDataAvailable() method 71 // needs to be called. Invoking that method may generate additional main 72 // thread runnables. 73 virtual bool NeedOnDataAvailable() = 0; 74 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; 78 79 virtual void OnReportPerformanceTiming() {} 80 81 virtual void OnNotifyNetworkMonitorAlternateStack(uint64_t aChannelID) {} 82 83 protected: 84 virtual ~FetchDriverObserver() = default; 85 86 virtual void OnResponseAvailableInternal( 87 SafeRefPtr<InternalResponse> aResponse) = 0; 88 89 nsCOMPtr<nsIConsoleReportCollector> mReporter; 90 91 private: 92 bool mGotResponseAvailable; 93 }; 94 95 class AlternativeDataStreamListener; 96 97 class FetchDriver final : public nsIChannelEventSink, 98 public nsIInterfaceRequestor, 99 public nsINetworkInterceptController, 100 public nsIThreadRetargetableStreamListener, 101 public AbortFollower { 102 public: 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 110 111 FetchDriver(SafeRefPtr<InternalRequest> aRequest, nsIPrincipal* aPrincipal, 112 nsILoadGroup* aLoadGroup, nsIEventTarget* aMainThreadEventTarget, 113 nsICookieJarSettings* aCookieJarSettings, 114 PerformanceStorage* aPerformanceStorage, 115 net::ClassificationFlags aTrackingFlags); 116 117 nsresult Fetch(AbortSignalImpl* aSignalImpl, FetchDriverObserver* aObserver); 118 119 void SetDocument(Document* aDocument); 120 121 void SetCSPEventListener(nsICSPEventListener* aCSPEventListener); 122 123 void SetClientInfo(const ClientInfo& aClientInfo); 124 125 void SetController(const Maybe<ServiceWorkerDescriptor>& aController); 126 127 void SetWorkerScript(const nsACString& aWorkerScript) { 128 MOZ_ASSERT(!aWorkerScript.IsEmpty()); 129 mWorkerScript = aWorkerScript; 130 } 131 132 void SetOriginStack(UniquePtr<SerializedStackHolder>&& aOriginStack) { 133 mOriginStack = std::move(aOriginStack); 134 } 135 136 PerformanceTimingData* GetPerformanceTimingData(nsAString& aInitiatorType, 137 nsAString& aEntryName); 138 139 // AbortFollower 140 void RunAbortAlgorithm() override; 141 void FetchDriverAbortActions(AbortSignalImpl* aSignalImpl); 142 143 void EnableNetworkInterceptControl(); 144 145 void SetAssociatedBrowsingContextID(uint64_t aID) { 146 mAssociatedBrowsingContextID = aID; 147 } 148 149 void SetIsThirdPartyContext(const Maybe<bool> aIsThirdPartyWorker) { 150 mIsThirdPartyContext = aIsThirdPartyWorker; 151 } 152 153 void SetIsOn3PCBExceptionList(bool aIsOn3PCBExceptionList) { 154 mIsOn3PCBExceptionList = aIsOn3PCBExceptionList; 155 } 156 157 private: 158 nsCOMPtr<nsIPrincipal> mPrincipal; 159 nsCOMPtr<nsILoadGroup> mLoadGroup; 160 SafeRefPtr<InternalRequest> mRequest; 161 SafeRefPtr<InternalResponse> mResponse; 162 nsCOMPtr<nsIOutputStream> mPipeOutputStream; 163 164 // mutex to prevent race between OnDataAvailable (OMT) and main thread 165 // functions 166 Mutex mODAMutex; 167 // access to mObserver can race between FetchDriverAbortActions (main thread) 168 // and OnDataAvailable (OMT) 169 // See Bug 1810805 170 RefPtr<FetchDriverObserver> mObserver; 171 RefPtr<Document> mDocument; 172 nsCOMPtr<nsICSPEventListener> mCSPEventListener; 173 Maybe<ClientInfo> mClientInfo; 174 Maybe<ServiceWorkerDescriptor> mController; 175 nsCOMPtr<nsIChannel> mChannel; 176 UniquePtr<SRICheckDataVerifier> mSRIDataVerifier; 177 nsCOMPtr<nsIEventTarget> mMainThreadEventTarget; 178 179 nsCOMPtr<nsICookieJarSettings> mCookieJarSettings; 180 181 // This is set only when Fetch is used in workers. 182 RefPtr<PerformanceStorage> mPerformanceStorage; 183 184 SRIMetadata mSRIMetadata; 185 nsCString mWorkerScript; 186 UniquePtr<SerializedStackHolder> mOriginStack; 187 188 // This is written once in OnStartRequest on the main thread and then 189 // written/read in OnDataAvailable() on any thread. Necko guarantees 190 // that these do not overlap. 191 bool mNeedToObserveOnDataAvailable; 192 193 bool mIsTrackingFetch; 194 net::ClassificationFlags mTrackingFlags; 195 196 // Indicates whether the fetch request is from a third-party context. 197 Maybe<bool> mIsThirdPartyContext; 198 199 // Indicates whether the fetch request is on the 3PCB exception list. 200 bool mIsOn3PCBExceptionList; 201 202 RefPtr<AlternativeDataStreamListener> mAltDataListener; 203 bool mOnStopRequestCalled; 204 205 // This flag is true when this fetch has found a matching preload and is being 206 // satisfied by a its response. 207 bool mFromPreload = false; 208 // This flag is set in call to Abort() and spans the possible window this 209 // fetch doesn't have mChannel (to be cancelled) between reuse of the matching 210 // preload, that has already finished and dropped reference to its channel, 211 // and OnStartRequest notification. It let's us cancel the load when we get 212 // the channel in OnStartRequest. 213 bool mAborted = false; 214 215 #ifdef DEBUG 216 bool mResponseAvailableCalled; 217 bool mFetchCalled; 218 #endif 219 nsCOMPtr<nsINetworkInterceptController> mInterceptController; 220 221 uint64_t mAssociatedBrowsingContextID{0}; 222 223 friend class AlternativeDataStreamListener; 224 225 FetchDriver() = delete; 226 FetchDriver(const FetchDriver&) = delete; 227 FetchDriver& operator=(const FetchDriver&) = delete; 228 ~FetchDriver(); 229 230 already_AddRefed<PreloaderBase> FindPreload(nsIURI* aURI); 231 232 void UpdateReferrerInfoFromNewChannel(nsIChannel* aChannel); 233 234 nsresult HttpFetch(const nsACString& aPreferredAlternativeDataType = ""_ns); 235 // Returns the filtered response sent to the observer. 236 SafeRefPtr<InternalResponse> BeginAndGetFilteredResponse( 237 SafeRefPtr<InternalResponse> aResponse, bool aFoundOpaqueRedirect); 238 // Utility since not all cases need to do any post processing of the filtered 239 // response. 240 void FailWithNetworkError(nsresult rv); 241 242 void SetRequestHeaders(nsIHttpChannel* aChannel, bool aStripRequestBodyHeader, 243 bool aStripAuthHeader) const; 244 245 void FinishOnStopRequest(AlternativeDataStreamListener* aAltDataListener); 246 }; 247 248 } // namespace dom 249 } // namespace mozilla 250 251 #endif // mozilla_dom_FetchDriver_h