SubstitutingProtocolHandler.h (4659B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef SubstitutingProtocolHandler_h___ 8 #define SubstitutingProtocolHandler_h___ 9 10 #include "nsISubstitutingProtocolHandler.h" 11 12 #include "nsTHashMap.h" 13 #include "nsStandardURL.h" 14 #include "nsJARURI.h" 15 #include "mozilla/chrome/RegistryMessageUtils.h" 16 #include "mozilla/RWLock.h" 17 18 class nsIIOService; 19 20 namespace mozilla { 21 namespace net { 22 23 // 24 // Base class for resource://-like substitution protocols. 25 // 26 // If you add a new protocol, make sure to change nsChromeRegistryChrome 27 // to properly invoke CollectSubstitutions at the right time. 28 class SubstitutingProtocolHandler { 29 public: 30 explicit SubstitutingProtocolHandler(const char* aScheme, 31 bool aEnforceFileOrJar = true); 32 33 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SubstitutingProtocolHandler); 34 NS_DECL_NON_VIRTUAL_NSIPROTOCOLHANDLER; 35 NS_DECL_NON_VIRTUAL_NSISUBSTITUTINGPROTOCOLHANDLER; 36 37 bool HasSubstitution(const nsACString& aRoot) const { 38 AutoReadLock lock(const_cast<RWLock&>(mSubstitutionsLock)); 39 return mSubstitutions.Get(aRoot, nullptr); 40 } 41 42 nsresult NewURI(const nsACString& aSpec, const char* aCharset, 43 nsIURI* aBaseURI, nsIURI** aResult); 44 45 [[nodiscard]] nsresult CollectSubstitutions( 46 nsTArray<SubstitutionMapping>& aMappings); 47 48 protected: 49 virtual ~SubstitutingProtocolHandler() = default; 50 void ConstructInternal(); 51 52 [[nodiscard]] nsresult SendSubstitution(const nsACString& aRoot, 53 nsIURI* aBaseURI, uint32_t aFlags); 54 55 nsresult GetSubstitutionFlags(const nsACString& root, uint32_t* flags); 56 57 // Override this in the subclass to try additional lookups after checking 58 // mSubstitutions. 59 [[nodiscard]] virtual nsresult GetSubstitutionInternal( 60 const nsACString& aRoot, nsIURI** aResult) { 61 *aResult = nullptr; 62 return NS_ERROR_NOT_AVAILABLE; 63 } 64 65 // Override this in the subclass to check for special case when resolving URIs 66 // _before_ checking substitutions. 67 [[nodiscard]] virtual bool ResolveSpecialCases(const nsACString& aHost, 68 const nsACString& aPath, 69 const nsACString& aPathname, 70 nsACString& aResult) { 71 return false; 72 } 73 74 // This method should only return RESOLVE_JAR_URI when 75 // GetSubstitutionalInternal will return nsIJARURI instead of a nsIFileURL. 76 // Currently, this only happens on Android. 77 [[nodiscard]] virtual uint32_t GetJARFlags(const nsACString& aRoot) { 78 return 0; 79 } 80 81 // Override this in the subclass to check for special case when opening 82 // channels. 83 [[nodiscard]] virtual nsresult SubstituteChannel(nsIURI* uri, 84 nsILoadInfo* aLoadInfo, 85 nsIChannel** result) { 86 return NS_OK; 87 } 88 89 nsIIOService* IOService() { return mIOService; } 90 91 private: 92 struct SubstitutionEntry { 93 nsCOMPtr<nsIURI> baseURI; 94 uint32_t flags = 0; 95 }; 96 97 // Notifies all observers that a new substitution from |aRoot| to 98 // |aBaseURI| has been set/installed for this protocol handler. 99 void NotifyObservers(const nsACString& aRoot, nsIURI* aBaseURI); 100 101 nsCString mScheme; 102 103 RWLock mSubstitutionsLock; 104 nsTHashMap<nsCStringHashKey, SubstitutionEntry> mSubstitutions 105 MOZ_GUARDED_BY(mSubstitutionsLock); 106 nsCOMPtr<nsIIOService> mIOService; 107 108 // Returns a SubstitutingJARURI if |aUrl| maps to a |jar:| URI, 109 // otherwise will return |aURL| 110 nsresult ResolveJARURI(nsIURL* aURL, nsIURI** aResult); 111 112 // In general, we expect the principal of a document loaded from a 113 // substituting URI to be a content principal for that URI (rather than 114 // a principal for whatever is underneath). However, this only works if 115 // the protocol handler for the underlying URI doesn't set an explicit 116 // owner (which chrome:// does, for example). So we want to require that 117 // substituting URIs only map to other URIs of the same type, or to 118 // file:// and jar:// URIs. 119 // 120 // Enforcing this for ye olde resource:// URIs could carry compat risks, so 121 // we just try to enforce it on new protocols going forward. 122 bool mEnforceFileOrJar; 123 }; 124 125 } // namespace net 126 } // namespace mozilla 127 128 #endif /* SubstitutingProtocolHandler_h___ */