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