1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set sw=2 ts=8 et tw=80 : */ 3 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #ifndef mozilla_net_HttpChannelParent_h 9 #define mozilla_net_HttpChannelParent_h 10 11 #include "nsHttp.h" 12 #include "mozilla/net/PHttpChannelParent.h" 13 #include "mozilla/net/NeckoCommon.h" 14 #include "mozilla/net/NeckoParent.h" 15 #include "mozilla/MozPromise.h" 16 #include "nsIParentRedirectingChannel.h" 17 #include "nsIProgressEventSink.h" 18 #include "nsIChannelEventSink.h" 19 #include "nsIRedirectResultListener.h" 20 #include "nsHttpChannel.h" 21 #include "mozilla/dom/ipc/IdType.h" 22 #include "nsIMultiPartChannel.h" 23 24 class nsICacheEntry; 25 26 #define HTTP_CHANNEL_PARENT_IID \ 27 { \ 28 0x982b2372, 0x7aa5, 0x4e8a, { \ 29 0xbd, 0x9f, 0x89, 0x74, 0xd7, 0xf0, 0x58, 0xeb \ 30 } \ 31 } 32 33 namespace mozilla { 34 35 namespace dom { 36 class BrowserParent; 37 } // namespace dom 38 39 namespace net { 40 41 class HttpBackgroundChannelParent; 42 class ParentChannelListener; 43 class ChannelEventQueue; 44 45 // Note: nsIInterfaceRequestor must be the first base so that do_QueryObject() 46 // works correctly on this object, as it's needed to compute a void* pointing to 47 // the beginning of this object. 48 49 class HttpChannelParent final : public nsIInterfaceRequestor, 50 public PHttpChannelParent, 51 public nsIParentRedirectingChannel, 52 public nsIProgressEventSink, 53 public HttpChannelSecurityWarningReporter, 54 public nsIAsyncVerifyRedirectReadyCallback, 55 public nsIChannelEventSink, 56 public nsIRedirectResultListener, 57 public nsIMultiPartChannelListener { 58 virtual ~HttpChannelParent(); 59 60 public: 61 NS_DECL_ISUPPORTS 62 NS_DECL_NSIREQUESTOBSERVER 63 NS_DECL_NSISTREAMLISTENER 64 NS_DECL_NSIPARENTCHANNEL 65 NS_DECL_NSIPARENTREDIRECTINGCHANNEL 66 NS_DECL_NSIPROGRESSEVENTSINK 67 NS_DECL_NSIINTERFACEREQUESTOR 68 NS_DECL_NSIASYNCVERIFYREDIRECTREADYCALLBACK 69 NS_DECL_NSICHANNELEVENTSINK 70 NS_DECL_NSIREDIRECTRESULTLISTENER 71 NS_DECL_NSIMULTIPARTCHANNELLISTENER 72 73 NS_DECLARE_STATIC_IID_ACCESSOR(HTTP_CHANNEL_PARENT_IID) 74 75 HttpChannelParent(dom::BrowserParent* iframeEmbedding, 76 nsILoadContext* aLoadContext, 77 PBOverrideStatus aOverrideStatus); 78 79 [[nodiscard]] bool Init(const HttpChannelCreationArgs& aArgs); 80 81 // Forwarded to nsHttpChannel::SetApplyConversion. SetApplyConversion(bool aApplyConversion)82 void SetApplyConversion(bool aApplyConversion) { 83 if (mChannel) { 84 mChannel->SetApplyConversion(aApplyConversion); 85 } 86 } 87 88 [[nodiscard]] nsresult OpenAlternativeOutputStream( 89 const nsACString& type, int64_t predictedSize, 90 nsIAsyncOutputStream** _retval); 91 92 // Callbacks for each asynchronous tasks required in AsyncOpen 93 // procedure, will call InvokeAsyncOpen when all the expected 94 // tasks is finished successfully or when any failure happened. 95 // @see mAsyncOpenBarrier. 96 void TryInvokeAsyncOpen(nsresult aRv); 97 98 void InvokeAsyncOpen(nsresult rv); 99 100 // Calls SendSetPriority if mIPCClosed is false. 101 void DoSendSetPriority(int16_t aValue); 102 103 // Callback while background channel is ready. 104 void OnBackgroundParentReady(HttpBackgroundChannelParent* aBgParent); 105 // Callback while background channel is destroyed. 106 void OnBackgroundParentDestroyed(); 107 108 base::ProcessId OtherPid() const; 109 110 // Inform the child actor that our referrer info was modified late during 111 // BeginConnect. 112 void OverrideReferrerInfoDuringBeginConnect(nsIReferrerInfo* aReferrerInfo); 113 114 // Set the cookie string, which will be informed to the child actor during 115 // PHttpBackgroundChannel::OnStartRequest. Note that CookieService also sends 116 // the information to all actors via PContent, a main thread IPC, which could 117 // be slower than background IPC PHttpBackgroundChannel::OnStartRequest. 118 // Therefore, another cookie notification via PBackground is needed to 119 // guarantee the listener in child has the necessary cookies before 120 // OnStartRequest. 121 void SetCookie(nsCString&& aCookie); 122 123 using ChildEndpointPromise = 124 MozPromise<ipc::Endpoint<extensions::PStreamFilterChild>, bool, true>; 125 [[nodiscard]] RefPtr<ChildEndpointPromise> AttachStreamFilter( 126 Endpoint<extensions::PStreamFilterParent>&& aParentEndpoint, 127 Endpoint<extensions::PStreamFilterChild>&& aChildEndpoint); 128 129 protected: 130 // used to connect redirected-to channel in parent with just created 131 // ChildChannel. Used during redirects. 132 [[nodiscard]] bool ConnectChannel(const uint32_t& registrarId); 133 134 [[nodiscard]] bool DoAsyncOpen( 135 const URIParams& uri, const Maybe<URIParams>& originalUri, 136 const Maybe<URIParams>& docUri, nsIReferrerInfo* aReferrerInfo, 137 const Maybe<URIParams>& aAPIRedirectToURI, 138 const Maybe<URIParams>& topWindowUri, const uint32_t& loadFlags, 139 const RequestHeaderTuples& requestHeaders, const nsCString& requestMethod, 140 const Maybe<IPCStream>& uploadStream, const bool& uploadStreamHasHeaders, 141 const int16_t& priority, const uint32_t& classOfService, 142 const uint8_t& redirectionLimit, const bool& allowSTS, 143 const uint32_t& thirdPartyFlags, const bool& doResumeAt, 144 const uint64_t& startPos, const nsCString& entityID, 145 const bool& allowSpdy, const bool& allowHttp3, const bool& allowAltSvc, 146 const bool& beConservative, const bool& bypassProxy, 147 const uint32_t& tlsFlags, const Maybe<LoadInfoArgs>& aLoadInfoArgs, 148 const uint32_t& aCacheKey, const uint64_t& aRequestContextID, 149 const Maybe<CorsPreflightArgs>& aCorsPreflightArgs, 150 const uint32_t& aInitialRwin, const bool& aBlockAuthPrompt, 151 const bool& aAllowStaleCacheContent, 152 const bool& aPreferCacheLoadOverBypass, const nsCString& aContentTypeHint, 153 const uint32_t& aCorsMode, const uint32_t& aRedirectMode, 154 const uint64_t& aChannelId, const nsString& aIntegrityMetadata, 155 const uint64_t& aContentWindowId, 156 const nsTArray<PreferredAlternativeDataTypeParams>& 157 aPreferredAlternativeTypes, 158 const uint64_t& aTopBrowsingContextId, 159 const TimeStamp& aLaunchServiceWorkerStart, 160 const TimeStamp& aLaunchServiceWorkerEnd, 161 const TimeStamp& aDispatchFetchEventStart, 162 const TimeStamp& aDispatchFetchEventEnd, 163 const TimeStamp& aHandleFetchEventStart, 164 const TimeStamp& aHandleFetchEventEnd, 165 const bool& aForceMainDocumentChannel, 166 const TimeStamp& aNavigationStartTimeStamp); 167 168 virtual mozilla::ipc::IPCResult RecvSetPriority( 169 const int16_t& priority) override; 170 virtual mozilla::ipc::IPCResult RecvSetClassOfService( 171 const uint32_t& cos) override; 172 virtual mozilla::ipc::IPCResult RecvSuspend() override; 173 virtual mozilla::ipc::IPCResult RecvResume() override; 174 virtual mozilla::ipc::IPCResult RecvCancel( 175 const nsresult& status, const uint32_t& requestBlockingReason) override; 176 virtual mozilla::ipc::IPCResult RecvRedirect2Verify( 177 const nsresult& result, const RequestHeaderTuples& changedHeaders, 178 const uint32_t& aSourceRequestBlockingReason, 179 const Maybe<ChildLoadInfoForwarderArgs>& aTargetLoadInfoForwarder, 180 const uint32_t& loadFlags, nsIReferrerInfo* aReferrerInfo, 181 const Maybe<URIParams>& apiRedirectUri, 182 const Maybe<CorsPreflightArgs>& aCorsPreflightArgs) override; 183 virtual mozilla::ipc::IPCResult RecvDocumentChannelCleanup( 184 const bool& clearCacheEntry) override; 185 virtual mozilla::ipc::IPCResult RecvRemoveCorsPreflightCacheEntry( 186 const URIParams& uri, 187 const mozilla::ipc::PrincipalInfo& requestingPrincipal, 188 const OriginAttributes& originAttributes) override; 189 virtual mozilla::ipc::IPCResult RecvBytesRead(const int32_t& aCount) override; 190 virtual mozilla::ipc::IPCResult RecvOpenOriginalCacheInputStream() override; 191 virtual void ActorDestroy(ActorDestroyReason why) override; 192 193 friend class ParentChannelListener; 194 RefPtr<mozilla::dom::BrowserParent> mBrowserParent; 195 196 [[nodiscard]] nsresult ReportSecurityMessage( 197 const nsAString& aMessageTag, const nsAString& aMessageCategory) override; 198 nsresult LogBlockedCORSRequest(const nsAString& aMessage, 199 const nsACString& aCategory) override; 200 nsresult LogMimeTypeMismatch(const nsACString& aMessageName, bool aWarning, 201 const nsAString& aURL, 202 const nsAString& aContentType) override; 203 204 // Calls SendDeleteSelf and sets mIPCClosed to true because we should not 205 // send any more messages after that. Bug 1274886 206 [[nodiscard]] bool DoSendDeleteSelf(); 207 // Called to notify the parent channel to not send any more IPC messages. 208 virtual mozilla::ipc::IPCResult RecvDeletingChannel() override; 209 210 private: 211 void UpdateAndSerializeSecurityInfo(nsACString& aSerializedSecurityInfoOut); 212 213 // final step for Redirect2Verify procedure, will be invoked while both 214 // redirecting and redirected channel are ready or any error happened. 215 // OnRedirectVerifyCallback will be invoked for finishing the async 216 // redirect verification procedure. 217 void ContinueRedirect2Verify(const nsresult& aResult); 218 219 void AsyncOpenFailed(nsresult aRv); 220 221 // Request to pair with a HttpBackgroundChannelParent with the same channel 222 // id, a promise will be returned so the caller can append callbacks on it. 223 // If called multiple times before mBgParent is available, the same promise 224 // will be returned and the callbacks will be invoked in order. 225 [[nodiscard]] RefPtr<GenericNonExclusivePromise> WaitForBgParent(); 226 227 // Remove the association with background channel after main-thread IPC 228 // is about to be destroyed or no further event is going to be sent, i.e., 229 // DocumentChannelCleanup. 230 void CleanupBackgroundChannel(); 231 232 // Check if the channel needs to enable the flow control on the IPC channel. 233 // That is, we may suspend the channel if the ODA-s to child process are not 234 // consumed quickly enough. Otherwise, memory explosion could happen. 235 bool NeedFlowControl(); 236 int32_t mSendWindowSize; 237 238 friend class HttpBackgroundChannelParent; 239 240 RefPtr<HttpBaseChannel> mChannel; 241 nsCOMPtr<nsICacheEntry> mCacheEntry; 242 243 nsCOMPtr<nsIChannel> mRedirectChannel; 244 nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback; 245 246 nsCOMPtr<nsILoadContext> mLoadContext; 247 RefPtr<nsHttpHandler> mHttpHandler; 248 249 RefPtr<ParentChannelListener> mParentListener; 250 251 RefPtr<ChannelEventQueue> mEventQ; 252 253 RefPtr<HttpBackgroundChannelParent> mBgParent; 254 255 MozPromiseHolder<GenericNonExclusivePromise> mPromise; 256 MozPromiseRequestHolder<GenericNonExclusivePromise> mRequest; 257 258 // To calculate the delay caused by the e10s back-pressure suspension 259 TimeStamp mResumedTimestamp; 260 261 Atomic<bool> mIPCClosed; // PHttpChannel actor has been Closed() 262 263 // Corresponding redirect channel registrar Id. 0 means redirection is not 264 // started. 265 uint64_t mRedirectChannelId = 0; 266 267 PBOverrideStatus mPBOverride; 268 269 // Set to the canceled status value if the main channel was canceled. 270 nsresult mStatus; 271 272 // The referrer info, set during nsHttpChannel::BeginConnect, to override the 273 // original one. This info will be sent in OnStartRequest. 274 nsCOMPtr<nsIReferrerInfo> mOverrideReferrerInfo; 275 276 // The cookie string in Set-Cookie header. This info will be sent in 277 // OnStartRequest. 278 nsCString mCookie; 279 280 // OnStatus is always called before OnProgress. 281 // Set true in OnStatus if next OnProgress can be ignored 282 // since the information can be recontructed from ODA. 283 uint8_t mIgnoreProgress : 1; 284 285 uint8_t mSentRedirect1BeginFailed : 1; 286 uint8_t mReceivedRedirect2Verify : 1; 287 uint8_t mHasSuspendedByBackPressure : 1; 288 289 // Set if we get the result of and cache |mNeedFlowControl| 290 uint8_t mCacheNeedFlowControlInitialized : 1; 291 uint8_t mNeedFlowControl : 1; 292 uint8_t mSuspendedForFlowControl : 1; 293 294 // Defaults to false. Is set to true at the begining of OnStartRequest. 295 // Used to ensure methods can't be called before OnStartRequest. 296 uint8_t mAfterOnStartRequestBegun : 1; 297 298 // Number of events to wait before actually invoking AsyncOpen on the main 299 // channel. For each asynchronous step required before InvokeAsyncOpen, should 300 // increase 1 to mAsyncOpenBarrier and invoke TryInvokeAsyncOpen after 301 // finished. This attribute is main thread only. 302 uint8_t mAsyncOpenBarrier = 0; 303 304 // When true, ODAs are sent from the socket process to the child process 305 // directly. 306 uint8_t mDataSentToChildProcess : 1; 307 }; 308 309 NS_DEFINE_STATIC_IID_ACCESSOR(HttpChannelParent, HTTP_CHANNEL_PARENT_IID) 310 311 } // namespace net 312 } // namespace mozilla 313 314 #endif // mozilla_net_HttpChannelParent_h 315