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 nsCORSListenerProxy_h__
8 #define nsCORSListenerProxy_h__
9 
10 #include "nsIStreamListener.h"
11 #include "nsIInterfaceRequestor.h"
12 #include "nsCOMPtr.h"
13 #include "nsString.h"
14 #include "nsIURI.h"
15 #include "nsTArray.h"
16 #include "nsIInterfaceRequestor.h"
17 #include "nsIChannelEventSink.h"
18 #include "nsIAsyncVerifyRedirectCallback.h"
19 #include "nsIThreadRetargetableStreamListener.h"
20 #include "mozilla/Attributes.h"
21 #include "mozilla/Atomics.h"
22 #include "mozilla/Mutex.h"
23 
24 class nsIURI;
25 class nsIPrincipal;
26 class nsINetworkInterceptController;
27 class nsICorsPreflightCallback;
28 
29 namespace mozilla {
30 namespace net {
31 class HttpChannelParent;
32 class nsHttpChannel;
33 }  // namespace net
34 }  // namespace mozilla
35 
36 enum class DataURIHandling { Allow, Disallow };
37 
38 enum class UpdateType { Default, InternalOrHSTSRedirect };
39 
40 class nsCORSListenerProxy final : public nsIStreamListener,
41                                   public nsIInterfaceRequestor,
42                                   public nsIChannelEventSink,
43                                   public nsIThreadRetargetableStreamListener {
44  public:
45   nsCORSListenerProxy(nsIStreamListener* aOuter,
46                       nsIPrincipal* aRequestingPrincipal,
47                       bool aWithCredentials);
48 
49   NS_DECL_THREADSAFE_ISUPPORTS
50   NS_DECL_NSIREQUESTOBSERVER
51   NS_DECL_NSISTREAMLISTENER
52   NS_DECL_NSIINTERFACEREQUESTOR
53   NS_DECL_NSICHANNELEVENTSINK
54   NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
55 
56   // Must be called at startup.
57   static void Startup();
58 
59   static void Shutdown();
60 
61   MOZ_MUST_USE nsresult Init(nsIChannel* aChannel,
62                              DataURIHandling aAllowDataURI);
63 
64   void SetInterceptController(
65       nsINetworkInterceptController* aInterceptController);
66 
67   // When CORS blocks a request, log the message to the web console, or the
68   // browser console if no valid inner window ID is found.
69   static void LogBlockedCORSRequest(uint64_t aInnerWindowID,
70                                     const nsAString& aMessage);
71 
72  private:
73   // Only HttpChannelParent can call RemoveFromCorsPreflightCache
74   friend class mozilla::net::HttpChannelParent;
75   // Only nsHttpChannel can invoke CORS preflights
76   friend class mozilla::net::nsHttpChannel;
77 
78   static void RemoveFromCorsPreflightCache(nsIURI* aURI,
79                                            nsIPrincipal* aRequestingPrincipal);
80   static MOZ_MUST_USE nsresult StartCORSPreflight(
81       nsIChannel* aRequestChannel, nsICorsPreflightCallback* aCallback,
82       nsTArray<nsCString>& aACUnsafeHeaders, nsIChannel** aPreflightChannel);
83 
84   ~nsCORSListenerProxy();
85 
86   MOZ_MUST_USE nsresult UpdateChannel(nsIChannel* aChannel,
87                                       DataURIHandling aAllowDataURI,
88                                       UpdateType aUpdateType);
89   MOZ_MUST_USE nsresult CheckRequestApproved(nsIRequest* aRequest);
90   MOZ_MUST_USE nsresult CheckPreflightNeeded(nsIChannel* aChannel,
91                                              UpdateType aUpdateType);
92 
93   nsCOMPtr<nsIStreamListener> mOuterListener;
94   // The principal that originally kicked off the request
95   nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
96   // The principal to use for our Origin header ("source origin" in spec terms).
97   // This can get changed during redirects, unlike mRequestingPrincipal.
98   nsCOMPtr<nsIPrincipal> mOriginHeaderPrincipal;
99   nsCOMPtr<nsIInterfaceRequestor> mOuterNotificationCallbacks;
100   nsCOMPtr<nsINetworkInterceptController> mInterceptController;
101   bool mWithCredentials;
102   mozilla::Atomic<bool, mozilla::Relaxed> mRequestApproved;
103   // Please note that the member variable mHasBeenCrossSite may rely on the
104   // promise that the CSP directive 'upgrade-insecure-requests' upgrades
105   // an http: request to https: in nsHttpChannel::Connect() and hence
106   // a request might not be marked as cross site request based on that promise.
107   bool mHasBeenCrossSite;
108   // Under e10s, logging happens in the child process. Keep a reference to the
109   // creator nsIHttpChannel in order to find the way back to the child. Released
110   // in OnStopRequest().
111   nsCOMPtr<nsIHttpChannel> mHttpChannel;
112 #ifdef DEBUG
113   bool mInited;
114 #endif
115 
116   // only locking mOuterListener, because it can be used on different threads.
117   // We guarantee that OnStartRequest, OnDataAvailable and OnStopReques will be
118   // called in order, but to make tsan happy we will lock mOuterListener.
119   mutable mozilla::Mutex mMutex;
120 };
121 
122 #endif
123