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