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