ExtensionProtocolHandler.h (11090B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef ExtensionProtocolHandler_h___ 7 #define ExtensionProtocolHandler_h___ 8 9 #include "mozilla/net/NeckoParent.h" 10 #include "mozilla/LazyIdleThread.h" 11 #include "mozilla/Result.h" 12 #include "SubstitutingProtocolHandler.h" 13 14 namespace mozilla { 15 namespace net { 16 17 class ExtensionStreamGetter; 18 19 class ExtensionProtocolHandler final : public nsISubstitutingProtocolHandler, 20 public SubstitutingProtocolHandler, 21 public nsSupportsWeakReference { 22 public: 23 NS_DECL_ISUPPORTS_INHERITED 24 NS_FORWARD_NSIPROTOCOLHANDLER(SubstitutingProtocolHandler::) 25 NS_FORWARD_NSISUBSTITUTINGPROTOCOLHANDLER(SubstitutingProtocolHandler::) 26 27 static already_AddRefed<ExtensionProtocolHandler> GetSingleton(); 28 29 /** 30 * To be called in the parent process to obtain an input stream for a 31 * a web accessible resource from an unpacked WebExtension dir. 32 * 33 * @param aChildURI a moz-extension URI sent from the child that refers 34 * to a web accessible resource file in an enabled unpacked extension 35 * @param aTerminateSender out param set to true when the params are invalid 36 * and indicate the child should be terminated. If |aChildURI| is 37 * not a moz-extension URI, the child is in an invalid state and 38 * should be terminated. 39 * @return NS_OK with |aTerminateSender| set to false on success. On 40 * failure, returns an error and sets |aTerminateSender| to indicate 41 * whether or not the child process should be terminated. 42 * A moz-extension URI from the child that doesn't resolve to a 43 * resource file within the extension could be the result of a bug 44 * in the extension and doesn't result in |aTerminateSender| being 45 * set to true. 46 */ 47 Result<nsCOMPtr<nsIInputStream>, nsresult> NewStream(nsIURI* aChildURI, 48 bool* aTerminateSender); 49 50 /** 51 * To be called in the parent process to obtain a file descriptor for an 52 * enabled WebExtension JAR file. 53 * 54 * @param aChildURI a moz-extension URI sent from the child that refers 55 * to a web accessible resource file in an enabled unpacked extension 56 * @param aTerminateSender out param set to true when the params are invalid 57 * and indicate the child should be terminated. If |aChildURI| is 58 * not a moz-extension URI, the child is in an invalid state and 59 * should be terminated. 60 * @param aPromise a promise that will be resolved asynchronously when the 61 * file descriptor is available. 62 * @return NS_OK with |aTerminateSender| set to false on success. On 63 * failure, returns an error and sets |aTerminateSender| to indicate 64 * whether or not the child process should be terminated. 65 * A moz-extension URI from the child that doesn't resolve to an 66 * enabled WebExtension JAR could be the result of a bug in the 67 * extension and doesn't result in |aTerminateSender| being 68 * set to true. 69 */ 70 Result<Ok, nsresult> NewFD(nsIURI* aChildURI, bool* aTerminateSender, 71 NeckoParent::GetExtensionFDResolver& aResolve); 72 73 protected: 74 ~ExtensionProtocolHandler() = default; 75 76 private: 77 explicit ExtensionProtocolHandler(); 78 79 [[nodiscard]] bool ResolveSpecialCases(const nsACString& aHost, 80 const nsACString& aPath, 81 const nsACString& aPathname, 82 nsACString& aResult) override; 83 84 // |result| is an inout param. On entry to this function, *result 85 // is expected to be non-null and already addrefed. This function 86 // may release the object stored in *result on entry and write 87 // a new pointer to an already addrefed channel to *result. 88 [[nodiscard]] virtual nsresult SubstituteChannel( 89 nsIURI* uri, nsILoadInfo* aLoadInfo, nsIChannel** result) override; 90 91 /** 92 * For moz-extension URI's that resolve to file or JAR URI's, replaces 93 * the provided channel with a channel that will proxy the load to the 94 * parent process. For moz-extension URI's that resolve to other types 95 * of URI's (not file or JAR), the provide channel is not replaced and 96 * NS_OK is returned. 97 * 98 * @param aURI the moz-extension URI 99 * @param aLoadInfo the loadinfo for the request 100 * @param aRetVal in/out channel param referring to the channel that 101 * might need to be substituted with a remote channel. 102 * @return NS_OK if the channel does not need to be substituted or 103 * or the replacement channel was created successfully. 104 * Otherwise returns an error. 105 */ 106 Result<Ok, nsresult> SubstituteRemoteChannel(nsIURI* aURI, 107 nsILoadInfo* aLoadInfo, 108 nsIChannel** aRetVal); 109 110 /** 111 * Replaces a file channel with a remote file channel for loading a 112 * web accessible resource for an unpacked extension from the parent. 113 * 114 * @param aURI the moz-extension URI 115 * @param aLoadInfo the loadinfo for the request 116 * @param aResolvedFileSpec the resolved URI spec for the file. 117 * @param aRetVal in/out param referring to the new remote channel. 118 * The reference to the input param file channel is dropped and 119 * replaced with a reference to a new channel that remotes 120 * the file access. The new channel encapsulates a request to 121 * the parent for an IPCStream for the file. 122 */ 123 void SubstituteRemoteFileChannel(nsIURI* aURI, nsILoadInfo* aLoadinfo, 124 nsACString& aResolvedFileSpec, 125 nsIChannel** aRetVal); 126 127 /** 128 * Replaces a JAR channel with a remote JAR channel for loading a 129 * an extension JAR file from the parent. 130 * 131 * @param aURI the moz-extension URI 132 * @param aLoadInfo the loadinfo for the request 133 * @param aResolvedFileSpec the resolved URI spec for the file. 134 * @param aRetVal in/out param referring to the new remote channel. 135 * The input param JAR channel is replaced with a new channel 136 * that remotes the JAR file access. The new channel encapsulates 137 * a request to the parent for the JAR file FD. 138 */ 139 Result<Ok, nsresult> SubstituteRemoteJarChannel(nsIURI* aURI, 140 nsILoadInfo* aLoadinfo, 141 nsACString& aResolvedSpec, 142 nsIChannel** aRetVal); 143 144 /** 145 * Sets the aResult outparam to true if this unpacked extension load of 146 * a resource that is outside the extension dir should be allowed. This 147 * is only allowed for system extensions on Mac and Linux dev builds. 148 * 149 * @param aExtensionDir the extension directory. Argument must be an 150 * nsIFile for which Normalize() has already been called. 151 * @param aRequestedFile the requested web-accessible resource file. Argument 152 * must be an nsIFile for which Normalize() has already been called. 153 */ 154 Result<bool, nsresult> AllowExternalResource(nsIFile* aExtensionDir, 155 nsIFile* aRequestedFile); 156 157 // Set the channel's content type using the provided URI's type 158 static void SetContentType(nsIURI* aURI, nsIChannel* aChannel); 159 160 // Gets a SimpleChannel that wraps the provided ExtensionStreamGetter 161 static void NewSimpleChannel(nsIURI* aURI, nsILoadInfo* aLoadinfo, 162 ExtensionStreamGetter* aStreamGetter, 163 nsIChannel** aRetVal); 164 165 // Gets a SimpleChannel that wraps the provided channel 166 static void NewSimpleChannel(nsIURI* aURI, nsILoadInfo* aLoadinfo, 167 nsIChannel* aChannel, nsIChannel** aRetVal); 168 169 #if defined(XP_MACOSX) 170 /** 171 * Sets the aResult outparam to true if we are a developer build with the 172 * repo dir environment variable set and the requested file resides in the 173 * repo dir. Developer builds may load system extensions with web-accessible 174 * resources that are symlinks to files in the repo dir. This method is for 175 * checking if an unpacked resource requested by the child is from the repo. 176 * The requested file must be already Normalized(). Only compile this for 177 * Mac because the repo dir isn't always available on Linux. 178 * 179 * @param aRequestedFile the requested web-accessible resource file. Argument 180 * must be an nsIFile for which Normalize() has already been called. 181 */ 182 Result<bool, nsresult> DevRepoContains(nsIFile* aRequestedFile); 183 184 // On development builds, this points to development repo. Lazily set. 185 nsCOMPtr<nsIFile> mDevRepo; 186 187 // Set to true once we've already tried to load the dev repo path, 188 // allowing for lazy initialization of |mDevRepo|. 189 bool mAlreadyCheckedDevRepo{false}; 190 #endif /* XP_MACOSX */ 191 192 #if !defined(XP_WIN) 193 /** 194 * Sets the aResult outparam to true if we are a developer build and the 195 * provided directory is within the NS_GRE_DIR directory. Developer builds 196 * may load system extensions with web-accessible resources that are symlinks 197 * to files outside of the extension dir to the repo dir. This method is for 198 * checking if an extension directory is within NS_GRE_DIR. In that case, we 199 * consider the extension a system extension and allow it to use symlinks to 200 * resources outside of the extension dir. This exception is only applied 201 * to loads for unpacked extensions in unpackaged developer builds. 202 * The requested dir must be already Normalized(). 203 * 204 * @param aExtensionDir the extension directory. Argument must be an 205 * nsIFile for which Normalize() has already been called. 206 */ 207 Result<bool, nsresult> AppDirContains(nsIFile* aExtensionDir); 208 209 // On development builds, cache the NS_GRE_DIR repo. Lazily set. 210 nsCOMPtr<nsIFile> mAppDir; 211 212 // Set to true once we've already read the AppDir, allowing for lazy 213 // initialization of |mAppDir|. 214 bool mAlreadyCheckedAppDir{false}; 215 #endif /* !defined(XP_WIN) */ 216 217 // Used for opening JAR files off the main thread when we just need to 218 // obtain a file descriptor to send back to the child. 219 RefPtr<mozilla::LazyIdleThread> mFileOpenerThread; 220 221 // To allow parent IPDL actors to invoke methods on this handler when 222 // handling moz-extension requests from the child. 223 static StaticRefPtr<ExtensionProtocolHandler> sSingleton; 224 225 // Set to true when this instance of the handler must proxy loads of 226 // extension web-accessible resources to the parent process. 227 bool mUseRemoteFileChannels; 228 }; 229 230 } // namespace net 231 } // namespace mozilla 232 233 #endif /* ExtensionProtocolHandler_h___ */