1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=4 sw=2 sts=2 et cin: */
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 nsNetUtil_h__
8 #define nsNetUtil_h__
9 
10 #include <functional>
11 #include "mozilla/Maybe.h"
12 #include "mozilla/ResultExtensions.h"
13 #include "nsCOMPtr.h"
14 #include "nsIInterfaceRequestor.h"
15 #include "nsIInterfaceRequestorUtils.h"
16 #include "nsILoadGroup.h"
17 #include "nsINestedURI.h"
18 #include "nsINetUtil.h"
19 #include "nsIRequest.h"
20 #include "nsILoadInfo.h"
21 #include "nsIIOService.h"
22 #include "nsIURI.h"
23 #include "mozilla/NotNull.h"
24 #include "mozilla/Services.h"
25 #include "mozilla/Unused.h"
26 #include "nsNetCID.h"
27 #include "nsReadableUtils.h"
28 #include "nsServiceManagerUtils.h"
29 #include "nsString.h"
30 
31 class nsIPrincipal;
32 class nsIAsyncStreamCopier;
33 class nsIAuthPrompt;
34 class nsIAuthPrompt2;
35 class nsIChannel;
36 class nsIChannelPolicy;
37 class nsICookieJarSettings;
38 class nsIDownloadObserver;
39 class nsIEventTarget;
40 class nsIFileProtocolHandler;
41 class nsIFileStream;
42 class nsIHttpChannel;
43 class nsIInputStream;
44 class nsIInputStreamPump;
45 class nsIInterfaceRequestor;
46 class nsIOutputStream;
47 class nsIParentChannel;
48 class nsIPersistentProperties;
49 class nsIProxyInfo;
50 class nsIRequestObserver;
51 class nsIStreamListener;
52 class nsIStreamLoader;
53 class nsIStreamLoaderObserver;
54 class nsIIncrementalStreamLoader;
55 class nsIIncrementalStreamLoaderObserver;
56 
57 namespace mozilla {
58 class Encoding;
59 class OriginAttributes;
60 namespace dom {
61 class ClientInfo;
62 class PerformanceStorage;
63 class ServiceWorkerDescriptor;
64 }  // namespace dom
65 
66 namespace ipc {
67 class FileDescriptor;
68 }  // namespace ipc
69 
70 }  // namespace mozilla
71 
72 template <class>
73 class nsCOMPtr;
74 template <typename>
75 struct already_AddRefed;
76 
77 already_AddRefed<nsIIOService> do_GetIOService(nsresult* error = nullptr);
78 
79 already_AddRefed<nsINetUtil> do_GetNetUtil(nsresult* error = nullptr);
80 
81 // private little helper function... don't call this directly!
82 nsresult net_EnsureIOService(nsIIOService** ios, nsCOMPtr<nsIIOService>& grip);
83 
84 nsresult NS_NewURI(nsIURI** aURI, const nsACString& spec,
85                    const char* charset = nullptr, nsIURI* baseURI = nullptr);
86 
87 nsresult NS_NewURI(nsIURI** result, const nsACString& spec,
88                    mozilla::NotNull<const mozilla::Encoding*> encoding,
89                    nsIURI* baseURI = nullptr);
90 
91 nsresult NS_NewURI(nsIURI** result, const nsAString& spec,
92                    const char* charset = nullptr, nsIURI* baseURI = nullptr);
93 
94 nsresult NS_NewURI(nsIURI** result, const nsAString& spec,
95                    mozilla::NotNull<const mozilla::Encoding*> encoding,
96                    nsIURI* baseURI = nullptr);
97 
98 nsresult NS_NewURI(nsIURI** result, const char* spec,
99                    nsIURI* baseURI = nullptr);
100 
101 nsresult NS_NewFileURI(
102     nsIURI** result, nsIFile* spec,
103     nsIIOService* ioService =
104         nullptr);  // pass in nsIIOService to optimize callers
105 
106 // These methods will only mutate the URI if the ref of aInput doesn't already
107 // match the ref we are trying to set.
108 // If aInput has no ref, and we are calling NS_GetURIWithoutRef, or
109 // NS_GetURIWithNewRef with an empty string, then aOutput will be the same
110 // as aInput. The same is true if aRef is already equal to the ref of aInput.
111 // This is OK because URIs are immutable and threadsafe.
112 // If the URI doesn't support ref fragments aOutput will be the same as aInput.
113 nsresult NS_GetURIWithNewRef(nsIURI* aInput, const nsACString& aRef,
114                              nsIURI** aOutput);
115 nsresult NS_GetURIWithoutRef(nsIURI* aInput, nsIURI** aOutput);
116 
117 nsresult NS_GetSanitizedURIStringFromURI(nsIURI* aUri,
118                                          nsAString& aSanitizedSpec);
119 
120 /*
121  * How to create a new Channel, using NS_NewChannel,
122  * NS_NewChannelWithTriggeringPrincipal,
123  * NS_NewInputStreamChannel, NS_NewChannelInternal
124  * and it's variations:
125  *
126  * What specific API function to use:
127  * * The NS_NewChannelInternal functions should almost never be directly
128  *   called outside of necko code.
129  * * If possible, use NS_NewChannel() providing a loading *nsINode*
130  * * If no loading *nsINode* is available, try calling NS_NewChannel() providing
131  *   a loading *ClientInfo*.
132  * * If no loading *nsINode* or *ClientInfo* are available, call NS_NewChannel()
133  *   providing a loading *nsIPrincipal*.
134  * * Call NS_NewChannelWithTriggeringPrincipal if the triggeringPrincipal
135  *   is different from the loadingPrincipal.
136  * * Call NS_NewChannelInternal() providing aLoadInfo object in cases where
137  *   you already have loadInfo object, e.g in case of a channel redirect.
138  *
139  * @param aURI
140  *        nsIURI from which to make a channel
141  * @param aLoadingNode
142  * @param aLoadingPrincipal
143  * @param aTriggeringPrincipal
144  * @param aSecurityFlags
145  * @param aContentPolicyType
146  *        These will be used as values for the nsILoadInfo object on the
147  *        created channel. For details, see nsILoadInfo in nsILoadInfo.idl
148  *
149  * Please note, if you provide both a loadingNode and a loadingPrincipal,
150  * then loadingPrincipal must be equal to loadingNode->NodePrincipal().
151  * But less error prone is to just supply a loadingNode.
152  *
153  * Note, if you provide a loading ClientInfo its principal must match the
154  * loading principal.  Currently you must pass both as the loading principal
155  * may have additional mutable values like CSP on it.  In the future these
156  * will be removed from nsIPrincipal and the API can be changed to take just
157  * the loading ClientInfo.
158  *
159  * Keep in mind that URIs coming from a webpage should *never* use the
160  * systemPrincipal as the loadingPrincipal.
161  */
162 nsresult NS_NewChannelInternal(
163     nsIChannel** outChannel, nsIURI* aUri, nsINode* aLoadingNode,
164     nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
165     const mozilla::Maybe<mozilla::dom::ClientInfo>& aLoadingClientInfo,
166     const mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController,
167     nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
168     nsICookieJarSettings* aCookieJarSettings = nullptr,
169     mozilla::dom::PerformanceStorage* aPerformanceStorage = nullptr,
170     nsILoadGroup* aLoadGroup = nullptr,
171     nsIInterfaceRequestor* aCallbacks = nullptr,
172     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
173     nsIIOService* aIoService = nullptr, uint32_t aSandboxFlags = 0);
174 
175 // See NS_NewChannelInternal for usage and argument description
176 nsresult NS_NewChannelInternal(
177     nsIChannel** outChannel, nsIURI* aUri, nsILoadInfo* aLoadInfo,
178     mozilla::dom::PerformanceStorage* aPerformanceStorage = nullptr,
179     nsILoadGroup* aLoadGroup = nullptr,
180     nsIInterfaceRequestor* aCallbacks = nullptr,
181     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
182     nsIIOService* aIoService = nullptr);
183 
184 // See NS_NewChannelInternal for usage and argument description
185 nsresult /*NS_NewChannelWithNodeAndTriggeringPrincipal */
186 NS_NewChannelWithTriggeringPrincipal(
187     nsIChannel** outChannel, nsIURI* aUri, nsINode* aLoadingNode,
188     nsIPrincipal* aTriggeringPrincipal, nsSecurityFlags aSecurityFlags,
189     nsContentPolicyType aContentPolicyType,
190     mozilla::dom::PerformanceStorage* aPerformanceStorage = nullptr,
191     nsILoadGroup* aLoadGroup = nullptr,
192     nsIInterfaceRequestor* aCallbacks = nullptr,
193     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
194     nsIIOService* aIoService = nullptr);
195 
196 // See NS_NewChannelInternal for usage and argument description
197 nsresult NS_NewChannelWithTriggeringPrincipal(
198     nsIChannel** outChannel, nsIURI* aUri, nsIPrincipal* aLoadingPrincipal,
199     nsIPrincipal* aTriggeringPrincipal, nsSecurityFlags aSecurityFlags,
200     nsContentPolicyType aContentPolicyType,
201     nsICookieJarSettings* aCookieJarSettings = nullptr,
202     mozilla::dom::PerformanceStorage* aPerformanceStorage = nullptr,
203     nsILoadGroup* aLoadGroup = nullptr,
204     nsIInterfaceRequestor* aCallbacks = nullptr,
205     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
206     nsIIOService* aIoService = nullptr);
207 
208 // See NS_NewChannelInternal for usage and argument description
209 nsresult NS_NewChannelWithTriggeringPrincipal(
210     nsIChannel** outChannel, nsIURI* aUri, nsIPrincipal* aLoadingPrincipal,
211     nsIPrincipal* aTriggeringPrincipal,
212     const mozilla::dom::ClientInfo& aLoadingClientInfo,
213     const mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController,
214     nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
215     nsICookieJarSettings* aCookieJarSettings = nullptr,
216     mozilla::dom::PerformanceStorage* aPerformanceStorage = nullptr,
217     nsILoadGroup* aLoadGroup = nullptr,
218     nsIInterfaceRequestor* aCallbacks = nullptr,
219     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
220     nsIIOService* aIoService = nullptr);
221 
222 // See NS_NewChannelInternal for usage and argument description
223 nsresult NS_NewChannel(
224     nsIChannel** outChannel, nsIURI* aUri, nsINode* aLoadingNode,
225     nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
226     mozilla::dom::PerformanceStorage* aPerformanceStorage = nullptr,
227     nsILoadGroup* aLoadGroup = nullptr,
228     nsIInterfaceRequestor* aCallbacks = nullptr,
229     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
230     nsIIOService* aIoService = nullptr, uint32_t aSandboxFlags = 0);
231 
232 // See NS_NewChannelInternal for usage and argument description
233 nsresult NS_NewChannel(
234     nsIChannel** outChannel, nsIURI* aUri, nsIPrincipal* aLoadingPrincipal,
235     nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
236     nsICookieJarSettings* aCookieJarSettings = nullptr,
237     mozilla::dom::PerformanceStorage* aPerformanceStorage = nullptr,
238     nsILoadGroup* aLoadGroup = nullptr,
239     nsIInterfaceRequestor* aCallbacks = nullptr,
240     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
241     nsIIOService* aIoService = nullptr, uint32_t aSandboxFlags = 0);
242 
243 // See NS_NewChannelInternal for usage and argument description
244 nsresult NS_NewChannel(
245     nsIChannel** outChannel, nsIURI* aUri, nsIPrincipal* aLoadingPrincipal,
246     const mozilla::dom::ClientInfo& aLoadingClientInfo,
247     const mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController,
248     nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
249     nsICookieJarSettings* aCookieJarSettings = nullptr,
250     mozilla::dom::PerformanceStorage* aPerformanceStorage = nullptr,
251     nsILoadGroup* aLoadGroup = nullptr,
252     nsIInterfaceRequestor* aCallbacks = nullptr,
253     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
254     nsIIOService* aIoService = nullptr, uint32_t aSandboxFlags = 0);
255 
256 nsresult NS_GetIsDocumentChannel(nsIChannel* aChannel, bool* aIsDocument);
257 
258 nsresult NS_MakeAbsoluteURI(nsACString& result, const nsACString& spec,
259                             nsIURI* baseURI);
260 
261 nsresult NS_MakeAbsoluteURI(char** result, const char* spec, nsIURI* baseURI);
262 
263 nsresult NS_MakeAbsoluteURI(nsAString& result, const nsAString& spec,
264                             nsIURI* baseURI);
265 
266 /**
267  * This function is a helper function to get a scheme's default port.
268  */
269 int32_t NS_GetDefaultPort(const char* scheme,
270                           nsIIOService* ioService = nullptr);
271 
272 /**
273  * This function is a helper function to apply the ToAscii conversion
274  * to a string
275  */
276 bool NS_StringToACE(const nsACString& idn, nsACString& result);
277 
278 /**
279  * This function is a helper function to get a protocol's default port if the
280  * URI does not specify a port explicitly. Returns -1 if this protocol has no
281  * concept of ports or if there was an error getting the port.
282  */
283 int32_t NS_GetRealPort(nsIURI* aURI);
284 
285 nsresult NS_NewInputStreamChannelInternal(
286     nsIChannel** outChannel, nsIURI* aUri,
287     already_AddRefed<nsIInputStream> aStream, const nsACString& aContentType,
288     const nsACString& aContentCharset, nsILoadInfo* aLoadInfo);
289 
290 nsresult NS_NewInputStreamChannelInternal(
291     nsIChannel** outChannel, nsIURI* aUri,
292     already_AddRefed<nsIInputStream> aStream, const nsACString& aContentType,
293     const nsACString& aContentCharset, nsINode* aLoadingNode,
294     nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
295     nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType);
296 
297 nsresult NS_NewInputStreamChannel(nsIChannel** outChannel, nsIURI* aUri,
298                                   already_AddRefed<nsIInputStream> aStream,
299                                   nsIPrincipal* aLoadingPrincipal,
300                                   nsSecurityFlags aSecurityFlags,
301                                   nsContentPolicyType aContentPolicyType,
302                                   const nsACString& aContentType = ""_ns,
303                                   const nsACString& aContentCharset = ""_ns);
304 
305 nsresult NS_NewInputStreamChannelInternal(
306     nsIChannel** outChannel, nsIURI* aUri, const nsAString& aData,
307     const nsACString& aContentType, nsINode* aLoadingNode,
308     nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
309     nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
310     bool aIsSrcdocChannel = false);
311 
312 nsresult NS_NewInputStreamChannelInternal(nsIChannel** outChannel, nsIURI* aUri,
313                                           const nsAString& aData,
314                                           const nsACString& aContentType,
315                                           nsILoadInfo* aLoadInfo,
316                                           bool aIsSrcdocChannel = false);
317 
318 nsresult NS_NewInputStreamChannel(nsIChannel** outChannel, nsIURI* aUri,
319                                   const nsAString& aData,
320                                   const nsACString& aContentType,
321                                   nsIPrincipal* aLoadingPrincipal,
322                                   nsSecurityFlags aSecurityFlags,
323                                   nsContentPolicyType aContentPolicyType,
324                                   bool aIsSrcdocChannel = false);
325 
326 nsresult NS_NewInputStreamPump(nsIInputStreamPump** aResult,
327                                already_AddRefed<nsIInputStream> aStream,
328                                uint32_t aSegsize = 0, uint32_t aSegcount = 0,
329                                bool aCloseWhenDone = false,
330                                nsIEventTarget* aMainThreadTarget = nullptr);
331 
332 nsresult NS_NewLoadGroup(nsILoadGroup** result, nsIRequestObserver* obs);
333 
334 // Create a new nsILoadGroup that will match the given principal.
335 nsresult NS_NewLoadGroup(nsILoadGroup** aResult, nsIPrincipal* aPrincipal);
336 
337 // Determine if the given loadGroup/principal pair will produce a principal
338 // with similar permissions when passed to NS_NewChannel().  This checks for
339 // things like making sure the browser element flag matches.  Without
340 // an appropriate load group these values can be lost when getting the result
341 // principal back out of the channel.  Null principals are also always allowed
342 // as they do not have permissions to actually use the load group.
343 bool NS_LoadGroupMatchesPrincipal(nsILoadGroup* aLoadGroup,
344                                   nsIPrincipal* aPrincipal);
345 
346 nsresult NS_NewDownloader(nsIStreamListener** result,
347                           nsIDownloadObserver* observer,
348                           nsIFile* downloadLocation = nullptr);
349 
350 nsresult NS_NewStreamLoader(nsIStreamLoader** result,
351                             nsIStreamLoaderObserver* observer,
352                             nsIRequestObserver* requestObserver = nullptr);
353 
354 nsresult NS_NewIncrementalStreamLoader(
355     nsIIncrementalStreamLoader** result,
356     nsIIncrementalStreamLoaderObserver* observer);
357 
358 nsresult NS_NewStreamLoaderInternal(
359     nsIStreamLoader** outStream, nsIURI* aUri,
360     nsIStreamLoaderObserver* aObserver, nsINode* aLoadingNode,
361     nsIPrincipal* aLoadingPrincipal, nsSecurityFlags aSecurityFlags,
362     nsContentPolicyType aContentPolicyType, nsILoadGroup* aLoadGroup = nullptr,
363     nsIInterfaceRequestor* aCallbacks = nullptr,
364     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL);
365 
366 nsresult NS_NewStreamLoader(nsIStreamLoader** outStream, nsIURI* aUri,
367                             nsIStreamLoaderObserver* aObserver,
368                             nsINode* aLoadingNode,
369                             nsSecurityFlags aSecurityFlags,
370                             nsContentPolicyType aContentPolicyType,
371                             nsILoadGroup* aLoadGroup = nullptr,
372                             nsIInterfaceRequestor* aCallbacks = nullptr,
373                             nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL);
374 
375 nsresult NS_NewStreamLoader(nsIStreamLoader** outStream, nsIURI* aUri,
376                             nsIStreamLoaderObserver* aObserver,
377                             nsIPrincipal* aLoadingPrincipal,
378                             nsSecurityFlags aSecurityFlags,
379                             nsContentPolicyType aContentPolicyType,
380                             nsILoadGroup* aLoadGroup = nullptr,
381                             nsIInterfaceRequestor* aCallbacks = nullptr,
382                             nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL);
383 
384 nsresult NS_NewSyncStreamListener(nsIStreamListener** result,
385                                   nsIInputStream** stream);
386 
387 /**
388  * Implement the nsIChannel::Open(nsIInputStream**) method using the channel's
389  * AsyncOpen method.
390  *
391  * NOTE: Reading from the returned nsIInputStream may spin the current
392  * thread's event queue, which could result in any event being processed.
393  */
394 nsresult NS_ImplementChannelOpen(nsIChannel* channel, nsIInputStream** result);
395 
396 nsresult NS_NewRequestObserverProxy(nsIRequestObserver** result,
397                                     nsIRequestObserver* observer,
398                                     nsISupports* context);
399 
400 nsresult NS_NewSimpleStreamListener(nsIStreamListener** result,
401                                     nsIOutputStream* sink,
402                                     nsIRequestObserver* observer = nullptr);
403 
404 nsresult NS_CheckPortSafety(int32_t port, const char* scheme,
405                             nsIIOService* ioService = nullptr);
406 
407 // Determine if this URI is using a safe port.
408 nsresult NS_CheckPortSafety(nsIURI* uri);
409 
410 nsresult NS_NewProxyInfo(const nsACString& type, const nsACString& host,
411                          int32_t port, uint32_t flags, nsIProxyInfo** result);
412 
413 nsresult NS_GetFileProtocolHandler(nsIFileProtocolHandler** result,
414                                    nsIIOService* ioService = nullptr);
415 
416 nsresult NS_GetFileFromURLSpec(const nsACString& inURL, nsIFile** result,
417                                nsIIOService* ioService = nullptr);
418 
419 nsresult NS_GetURLSpecFromFile(nsIFile* file, nsACString& url,
420                                nsIIOService* ioService = nullptr);
421 
422 /**
423  * Converts the nsIFile to the corresponding URL string.
424  * Should only be called on files which are not directories,
425  * is otherwise identical to NS_GetURLSpecFromFile, but is
426  * usually more efficient.
427  * Warning: this restriction may not be enforced at runtime!
428  */
429 nsresult NS_GetURLSpecFromActualFile(nsIFile* file, nsACString& url,
430                                      nsIIOService* ioService = nullptr);
431 
432 /**
433  * Converts the nsIFile to the corresponding URL string.
434  * Should only be called on files which are directories,
435  * is otherwise identical to NS_GetURLSpecFromFile, but is
436  * usually more efficient.
437  * Warning: this restriction may not be enforced at runtime!
438  */
439 nsresult NS_GetURLSpecFromDir(nsIFile* file, nsACString& url,
440                               nsIIOService* ioService = nullptr);
441 
442 /**
443  * Obtains the referrer for a given channel.  This first tries to obtain the
444  * referrer from the property docshell.internalReferrer, and if that doesn't
445  * work and the channel is an nsIHTTPChannel, we check it's referrer property.
446  *
447  */
448 void NS_GetReferrerFromChannel(nsIChannel* channel, nsIURI** referrer);
449 
450 nsresult NS_ParseRequestContentType(const nsACString& rawContentType,
451                                     nsCString& contentType,
452                                     nsCString& contentCharset);
453 
454 nsresult NS_ParseResponseContentType(const nsACString& rawContentType,
455                                      nsCString& contentType,
456                                      nsCString& contentCharset);
457 
458 nsresult NS_ExtractCharsetFromContentType(const nsACString& rawContentType,
459                                           nsCString& contentCharset,
460                                           bool* hadCharset,
461                                           int32_t* charsetStart,
462                                           int32_t* charsetEnd);
463 
464 nsresult NS_NewLocalFileInputStream(nsIInputStream** result, nsIFile* file,
465                                     int32_t ioFlags = -1, int32_t perm = -1,
466                                     int32_t behaviorFlags = 0);
467 
468 mozilla::Result<nsCOMPtr<nsIInputStream>, nsresult> NS_NewLocalFileInputStream(
469     nsIFile* file, int32_t ioFlags = -1, int32_t perm = -1,
470     int32_t behaviorFlags = 0);
471 
472 nsresult NS_NewLocalFileOutputStream(nsIOutputStream** result, nsIFile* file,
473                                      int32_t ioFlags = -1, int32_t perm = -1,
474                                      int32_t behaviorFlags = 0);
475 
476 mozilla::Result<nsCOMPtr<nsIOutputStream>, nsresult>
477 NS_NewLocalFileOutputStream(nsIFile* file, int32_t ioFlags = -1,
478                             int32_t perm = -1, int32_t behaviorFlags = 0);
479 
480 nsresult NS_NewLocalFileOutputStream(nsIOutputStream** result,
481                                      const mozilla::ipc::FileDescriptor& fd);
482 
483 // returns a file output stream which can be QI'ed to nsISafeOutputStream.
484 nsresult NS_NewAtomicFileOutputStream(nsIOutputStream** result, nsIFile* file,
485                                       int32_t ioFlags = -1, int32_t perm = -1,
486                                       int32_t behaviorFlags = 0);
487 
488 // returns a file output stream which can be QI'ed to nsISafeOutputStream.
489 nsresult NS_NewSafeLocalFileOutputStream(nsIOutputStream** result,
490                                          nsIFile* file, int32_t ioFlags = -1,
491                                          int32_t perm = -1,
492                                          int32_t behaviorFlags = 0);
493 
494 nsresult NS_NewLocalFileStream(nsIFileStream** result, nsIFile* file,
495                                int32_t ioFlags = -1, int32_t perm = -1,
496                                int32_t behaviorFlags = 0);
497 
498 mozilla::Result<nsCOMPtr<nsIFileStream>, nsresult> NS_NewLocalFileStream(
499     nsIFile* file, int32_t ioFlags = -1, int32_t perm = -1,
500     int32_t behaviorFlags = 0);
501 
502 [[nodiscard]] nsresult NS_NewBufferedInputStream(
503     nsIInputStream** aResult, already_AddRefed<nsIInputStream> aInputStream,
504     uint32_t aBufferSize);
505 
506 mozilla::Result<nsCOMPtr<nsIInputStream>, nsresult> NS_NewBufferedInputStream(
507     already_AddRefed<nsIInputStream> aInputStream, uint32_t aBufferSize);
508 
509 // note: the resulting stream can be QI'ed to nsISafeOutputStream iff the
510 // provided stream supports it.
511 nsresult NS_NewBufferedOutputStream(
512     nsIOutputStream** aResult, already_AddRefed<nsIOutputStream> aOutputStream,
513     uint32_t aBufferSize);
514 
515 /**
516  * This function reads an inputStream and stores its content into a buffer. In
517  * general, you should avoid using this function because, it blocks the current
518  * thread until the operation is done.
519  * If the inputStream is async, the reading happens on an I/O thread.
520  *
521  * @param aInputStream the inputStream.
522  * @param aDest the destination buffer. if *aDest is null, it will be allocated
523  *              with the size of the written data. if aDest is not null, aCount
524  *              must greater than 0.
525  * @param aCount the amount of data to read. Use -1 if you want that all the
526  *               stream is read.
527  * @param aWritten this pointer will be used to store the number of data
528  *                 written in the buffer. If you don't need, pass nullptr.
529  */
530 nsresult NS_ReadInputStreamToBuffer(nsIInputStream* aInputStream, void** aDest,
531                                     int64_t aCount,
532                                     uint64_t* aWritten = nullptr);
533 
534 /**
535  * See the comment for NS_ReadInputStreamToBuffer
536  */
537 nsresult NS_ReadInputStreamToString(nsIInputStream* aInputStream,
538                                     nsACString& aDest, int64_t aCount,
539                                     uint64_t* aWritten = nullptr);
540 
541 nsresult NS_LoadPersistentPropertiesFromURISpec(
542     nsIPersistentProperties** outResult, const nsACString& aSpec);
543 
544 /**
545  * NS_QueryNotificationCallbacks implements the canonical algorithm for
546  * querying interfaces from a channel's notification callbacks.  It first
547  * searches the channel's notificationCallbacks attribute, and if the interface
548  * is not found there, then it inspects the notificationCallbacks attribute of
549  * the channel's loadGroup.
550  *
551  * Note: templatized only because nsIWebSocketChannel is currently not an
552  * nsIChannel.
553  */
554 template <class T>
NS_QueryNotificationCallbacks(T * channel,const nsIID & iid,void ** result)555 inline void NS_QueryNotificationCallbacks(T* channel, const nsIID& iid,
556                                           void** result) {
557   MOZ_ASSERT(channel, "null channel");
558   *result = nullptr;
559 
560   nsCOMPtr<nsIInterfaceRequestor> cbs;
561   mozilla::Unused << channel->GetNotificationCallbacks(getter_AddRefs(cbs));
562   if (cbs) cbs->GetInterface(iid, result);
563   if (!*result) {
564     // try load group's notification callbacks...
565     nsCOMPtr<nsILoadGroup> loadGroup;
566     mozilla::Unused << channel->GetLoadGroup(getter_AddRefs(loadGroup));
567     if (loadGroup) {
568       loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
569       if (cbs) cbs->GetInterface(iid, result);
570     }
571   }
572 }
573 
574 // template helper:
575 // Note: "class C" templatized only because nsIWebSocketChannel is currently not
576 // an nsIChannel.
577 
578 template <class C, class T>
NS_QueryNotificationCallbacks(C * channel,nsCOMPtr<T> & result)579 inline void NS_QueryNotificationCallbacks(C* channel, nsCOMPtr<T>& result) {
580   NS_QueryNotificationCallbacks(channel, NS_GET_TEMPLATE_IID(T),
581                                 getter_AddRefs(result));
582 }
583 
584 /**
585  * Alternate form of NS_QueryNotificationCallbacks designed for use by
586  * nsIChannel implementations.
587  */
NS_QueryNotificationCallbacks(nsIInterfaceRequestor * callbacks,nsILoadGroup * loadGroup,const nsIID & iid,void ** result)588 inline void NS_QueryNotificationCallbacks(nsIInterfaceRequestor* callbacks,
589                                           nsILoadGroup* loadGroup,
590                                           const nsIID& iid, void** result) {
591   *result = nullptr;
592 
593   if (callbacks) callbacks->GetInterface(iid, result);
594   if (!*result) {
595     // try load group's notification callbacks...
596     if (loadGroup) {
597       nsCOMPtr<nsIInterfaceRequestor> cbs;
598       loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
599       if (cbs) cbs->GetInterface(iid, result);
600     }
601   }
602 }
603 
604 /**
605  * Returns true if channel is using Private Browsing, or false if not.
606  * Returns false if channel's callbacks don't implement nsILoadContext.
607  */
608 bool NS_UsePrivateBrowsing(nsIChannel* channel);
609 
610 /**
611  * Returns true if the channel has visited any cross-origin URLs on any
612  * URLs that it was redirected through.
613  */
614 bool NS_HasBeenCrossOrigin(nsIChannel* aChannel, bool aReport = false);
615 
616 /**
617  * Returns true if the channel has a safe method.
618  */
619 bool NS_IsSafeMethodNav(nsIChannel* aChannel);
620 
621 // Unique first-party domain for separating the safebrowsing cookie.
622 // Note if this value is changed, code in test_cookiejars_safebrowsing.js and
623 // nsUrlClassifierHashCompleter.js should also be changed.
624 #define NECKO_SAFEBROWSING_FIRST_PARTY_DOMAIN \
625   "safebrowsing.86868755-6b82-4842-b301-72671a0db32e.mozilla"
626 
627 // Unique first-party domain for separating about uri.
628 #define ABOUT_URI_FIRST_PARTY_DOMAIN \
629   "about.ef2a7dd5-93bc-417f-a698-142c3116864f.mozilla"
630 
631 /**
632  * Wraps an nsIAuthPrompt so that it can be used as an nsIAuthPrompt2. This
633  * method is provided mainly for use by other methods in this file.
634  *
635  * *aAuthPrompt2 should be set to null before calling this function.
636  */
637 void NS_WrapAuthPrompt(nsIAuthPrompt* aAuthPrompt,
638                        nsIAuthPrompt2** aAuthPrompt2);
639 
640 /**
641  * Gets an auth prompt from an interface requestor. This takes care of wrapping
642  * an nsIAuthPrompt so that it can be used as an nsIAuthPrompt2.
643  */
644 void NS_QueryAuthPrompt2(nsIInterfaceRequestor* aCallbacks,
645                          nsIAuthPrompt2** aAuthPrompt);
646 
647 /**
648  * Gets an nsIAuthPrompt2 from a channel. Use this instead of
649  * NS_QueryNotificationCallbacks for better backwards compatibility.
650  */
651 void NS_QueryAuthPrompt2(nsIChannel* aChannel, nsIAuthPrompt2** aAuthPrompt);
652 
653 /* template helper */
654 template <class T>
NS_QueryNotificationCallbacks(nsIInterfaceRequestor * callbacks,nsILoadGroup * loadGroup,nsCOMPtr<T> & result)655 inline void NS_QueryNotificationCallbacks(nsIInterfaceRequestor* callbacks,
656                                           nsILoadGroup* loadGroup,
657                                           nsCOMPtr<T>& result) {
658   NS_QueryNotificationCallbacks(callbacks, loadGroup, NS_GET_TEMPLATE_IID(T),
659                                 getter_AddRefs(result));
660 }
661 
662 /* template helper */
663 template <class T>
NS_QueryNotificationCallbacks(const nsCOMPtr<nsIInterfaceRequestor> & aCallbacks,const nsCOMPtr<nsILoadGroup> & aLoadGroup,nsCOMPtr<T> & aResult)664 inline void NS_QueryNotificationCallbacks(
665     const nsCOMPtr<nsIInterfaceRequestor>& aCallbacks,
666     const nsCOMPtr<nsILoadGroup>& aLoadGroup, nsCOMPtr<T>& aResult) {
667   NS_QueryNotificationCallbacks(aCallbacks.get(), aLoadGroup.get(), aResult);
668 }
669 
670 /* template helper */
671 template <class T>
NS_QueryNotificationCallbacks(const nsCOMPtr<nsIChannel> & aChannel,nsCOMPtr<T> & aResult)672 inline void NS_QueryNotificationCallbacks(const nsCOMPtr<nsIChannel>& aChannel,
673                                           nsCOMPtr<T>& aResult) {
674   NS_QueryNotificationCallbacks(aChannel.get(), aResult);
675 }
676 
677 /**
678  * This function returns a nsIInterfaceRequestor instance that returns the
679  * same result as NS_QueryNotificationCallbacks when queried.  It is useful
680  * as the value for nsISocketTransport::securityCallbacks.
681  */
682 nsresult NS_NewNotificationCallbacksAggregation(
683     nsIInterfaceRequestor* callbacks, nsILoadGroup* loadGroup,
684     nsIEventTarget* target, nsIInterfaceRequestor** result);
685 
686 nsresult NS_NewNotificationCallbacksAggregation(
687     nsIInterfaceRequestor* callbacks, nsILoadGroup* loadGroup,
688     nsIInterfaceRequestor** result);
689 
690 /**
691  * Helper function for testing online/offline state of the browser.
692  */
693 bool NS_IsOffline();
694 
695 /**
696  * Helper functions for implementing nsINestedURI::innermostURI.
697  *
698  * Note that NS_DoImplGetInnermostURI is "private" -- call
699  * NS_ImplGetInnermostURI instead.
700  */
701 nsresult NS_DoImplGetInnermostURI(nsINestedURI* nestedURI, nsIURI** result);
702 
703 nsresult NS_ImplGetInnermostURI(nsINestedURI* nestedURI, nsIURI** result);
704 
705 /**
706  * Helper function for testing whether the given URI, or any of its
707  * inner URIs, has all the given protocol flags.
708  */
709 nsresult NS_URIChainHasFlags(nsIURI* uri, uint32_t flags, bool* result);
710 
711 /**
712  * Helper function for getting the innermost URI for a given URI.  The return
713  * value could be just the object passed in if it's not a nested URI.
714  */
715 already_AddRefed<nsIURI> NS_GetInnermostURI(nsIURI* aURI);
716 
717 /**
718  * Helper function for getting the host name of the innermost URI for a given
719  * URI.  The return value could be the host name of the URI passed in if it's
720  * not a nested URI.
721  */
NS_GetInnermostURIHost(nsIURI * aURI,nsACString & aHost)722 inline nsresult NS_GetInnermostURIHost(nsIURI* aURI, nsACString& aHost) {
723   aHost.Truncate();
724 
725   // This block is optimized in order to avoid the overhead of calling
726   // NS_GetInnermostURI() which incurs a lot of overhead in terms of
727   // AddRef/Release calls.
728   nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
729   if (nestedURI) {
730     // We have a nested URI!
731     nsCOMPtr<nsIURI> uri;
732     nsresult rv = nestedURI->GetInnermostURI(getter_AddRefs(uri));
733     if (NS_FAILED(rv)) {
734       return rv;
735     }
736 
737     rv = uri->GetAsciiHost(aHost);
738     if (NS_FAILED(rv)) {
739       return rv;
740     }
741   } else {
742     // We have a non-nested URI!
743     nsresult rv = aURI->GetAsciiHost(aHost);
744     if (NS_FAILED(rv)) {
745       return rv;
746     }
747   }
748 
749   return NS_OK;
750 }
751 
752 /**
753  * Get the "final" URI for a channel.  This is either channel's load info
754  * resultPrincipalURI, if set, or GetOriginalURI.  In most cases (but not all)
755  * load info resultPrincipalURI, if set, corresponds to URI of the channel if
756  * it's required to represent the actual principal for the channel.
757  */
758 nsresult NS_GetFinalChannelURI(nsIChannel* channel, nsIURI** uri);
759 
760 // NS_SecurityHashURI must return the same hash value for any two URIs that
761 // compare equal according to NS_SecurityCompareURIs.  Unfortunately, in the
762 // case of files, it's not clear we can do anything better than returning
763 // the schemeHash, so hashing files degenerates to storing them in a list.
764 uint32_t NS_SecurityHashURI(nsIURI* aURI);
765 
766 bool NS_SecurityCompareURIs(nsIURI* aSourceURI, nsIURI* aTargetURI,
767                             bool aStrictFileOriginPolicy);
768 
769 bool NS_URIIsLocalFile(nsIURI* aURI);
770 
771 // When strict file origin policy is enabled, SecurityCompareURIs will fail for
772 // file URIs that do not point to the same local file. This call provides an
773 // alternate file-specific origin check that allows target files that are
774 // contained in the same directory as the source.
775 //
776 // https://developer.mozilla.org/en-US/docs/Same-origin_policy_for_file:_URIs
777 bool NS_RelaxStrictFileOriginPolicy(nsIURI* aTargetURI, nsIURI* aSourceURI,
778                                     bool aAllowDirectoryTarget = false);
779 
780 bool NS_IsInternalSameURIRedirect(nsIChannel* aOldChannel,
781                                   nsIChannel* aNewChannel, uint32_t aFlags);
782 
783 bool NS_IsHSTSUpgradeRedirect(nsIChannel* aOldChannel, nsIChannel* aNewChannel,
784                               uint32_t aFlags);
785 
786 nsresult NS_LinkRedirectChannels(uint64_t channelId,
787                                  nsIParentChannel* parentChannel,
788                                  nsIChannel** _result);
789 
790 /**
791  * Helper function which checks whether the channel can be
792  * openend using Open() or has to fall back to opening
793  * the channel using Open().
794  */
795 nsresult NS_MaybeOpenChannelUsingOpen(nsIChannel* aChannel,
796                                       nsIInputStream** aStream);
797 
798 /**
799  * Helper function which checks whether the channel can be
800  * openend using AsyncOpen() or has to fall back to opening
801  * the channel using AsyncOpen().
802  */
803 nsresult NS_MaybeOpenChannelUsingAsyncOpen(nsIChannel* aChannel,
804                                            nsIStreamListener* aListener);
805 
806 /**
807  * Returns nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP if `aHeader` is
808  * "require-corp" and nsILoadInfo::EMBEDDER_POLICY_NULL otherwise.
809  *
810  * See: https://mikewest.github.io/corpp/#parsing
811  */
812 nsILoadInfo::CrossOriginEmbedderPolicy
813 NS_GetCrossOriginEmbedderPolicyFromHeader(const nsACString& aHeader);
814 
815 /** Given the first (disposition) token from a Content-Disposition header,
816  * tell whether it indicates the content is inline or attachment
817  * @param aDispToken the disposition token from the content-disposition header
818  */
819 uint32_t NS_GetContentDispositionFromToken(const nsAString& aDispToken);
820 
821 /** Determine the disposition (inline/attachment) of the content based on the
822  * Content-Disposition header
823  * @param aHeader the content-disposition header (full value)
824  * @param aChan the channel the header came from
825  */
826 uint32_t NS_GetContentDispositionFromHeader(const nsACString& aHeader,
827                                             nsIChannel* aChan = nullptr);
828 
829 /** Extracts the filename out of a content-disposition header
830  * @param aFilename [out] The filename. Can be empty on error.
831  * @param aDisposition Value of a Content-Disposition header
832 
833  */
834 nsresult NS_GetFilenameFromDisposition(nsAString& aFilename,
835                                        const nsACString& aDisposition);
836 
837 /**
838  * Make sure Personal Security Manager is initialized
839  */
840 void net_EnsurePSMInit();
841 
842 /**
843  * Test whether a URI is "about:blank".  |uri| must not be null
844  */
845 bool NS_IsAboutBlank(nsIURI* uri);
846 
847 nsresult NS_GenerateHostPort(const nsCString& host, int32_t port,
848                              nsACString& hostLine);
849 
850 /**
851  * Sniff the content type for a given request or a given buffer.
852  *
853  * aSnifferType can be either NS_CONTENT_SNIFFER_CATEGORY or
854  * NS_DATA_SNIFFER_CATEGORY.  The function returns the sniffed content type
855  * in the aSniffedType argument.  This argument will not be modified if the
856  * content type could not be sniffed.
857  */
858 void NS_SniffContent(const char* aSnifferType, nsIRequest* aRequest,
859                      const uint8_t* aData, uint32_t aLength,
860                      nsACString& aSniffedType);
861 
862 /**
863  * Whether the channel was created to load a srcdoc document.
864  * Note that view-source:about:srcdoc is classified as a srcdoc document by
865  * this function, which may not be applicable everywhere.
866  */
867 bool NS_IsSrcdocChannel(nsIChannel* aChannel);
868 
869 /**
870  * Return true if the given string is a reasonable HTTP header value given the
871  * definition in RFC 2616 section 4.2.  Currently we don't pay the cost to do
872  * full, sctrict validation here since it would require fulling parsing the
873  * value.
874  */
875 bool NS_IsReasonableHTTPHeaderValue(const nsACString& aValue);
876 
877 /**
878  * Return true if the given string is a valid HTTP token per RFC 2616 section
879  * 2.2.
880  */
881 bool NS_IsValidHTTPToken(const nsACString& aToken);
882 
883 /**
884  * Strip the leading or trailing HTTP whitespace per fetch spec section 2.2.
885  */
886 void NS_TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest);
887 
888 /**
889  * Return true if the given request must be upgraded to HTTPS.
890  * If |aResultCallback| is provided and the storage is not ready to read, the
891  * result will be sent back through the callback and |aWillCallback| will be
892  * true. Otherwiew, the result will be set to |aShouldUpgrade| and
893  * |aWillCallback| is false.
894  */
895 nsresult NS_ShouldSecureUpgrade(
896     nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIPrincipal* aChannelResultPrincipal,
897     bool aPrivateBrowsing, bool aAllowSTS,
898     const mozilla::OriginAttributes& aOriginAttributes, bool& aShouldUpgrade,
899     std::function<void(bool, nsresult)>&& aResultCallback, bool& aWillCallback);
900 
901 /**
902  * Returns an https URI for channels that need to go through secure upgrades.
903  */
904 nsresult NS_GetSecureUpgradedURI(nsIURI* aURI, nsIURI** aUpgradedURI);
905 
906 nsresult NS_CompareLoadInfoAndLoadContext(nsIChannel* aChannel);
907 
908 /**
909  * Return true if this channel should be classified by the URL classifier.
910  */
911 bool NS_ShouldClassifyChannel(nsIChannel* aChannel);
912 
913 /**
914  * Helper to set the blocking reason on loadinfo of the channel.
915  */
916 nsresult NS_SetRequestBlockingReason(nsIChannel* channel, uint32_t reason);
917 nsresult NS_SetRequestBlockingReason(nsILoadInfo* loadInfo, uint32_t reason);
918 nsresult NS_SetRequestBlockingReasonIfNull(nsILoadInfo* loadInfo,
919                                            uint32_t reason);
920 
921 namespace mozilla {
922 namespace net {
923 
924 const static uint64_t kJS_MAX_SAFE_UINTEGER = +9007199254740991ULL;
925 const static int64_t kJS_MIN_SAFE_INTEGER = -9007199254740991LL;
926 const static int64_t kJS_MAX_SAFE_INTEGER = +9007199254740991LL;
927 
928 // Make sure a 64bit value can be captured by JS MAX_SAFE_INTEGER
929 bool InScriptableRange(int64_t val);
930 
931 // Make sure a 64bit value can be captured by JS MAX_SAFE_INTEGER
932 bool InScriptableRange(uint64_t val);
933 
934 /**
935  * Given the value of a single header field  (such as
936  * Content-Disposition and Content-Type) and the name of a parameter
937  * (e.g. filename, name, charset), returns the value of the parameter.
938  * See nsIMIMEHeaderParam.idl for more information.
939  *
940  * @param  aHeaderVal        a header string to get the value of a parameter
941  *                           from.
942  * @param  aParamName        the name of a MIME header parameter (e.g.
943  *                           filename, name, charset). If empty or nullptr,
944  *                           returns the first (possibly) _unnamed_ 'parameter'.
945  * @return the value of <code>aParamName</code> in Unichar(UTF-16).
946  */
947 nsresult GetParameterHTTP(const nsACString& aHeaderVal, const char* aParamName,
948                           nsAString& aResult);
949 
950 /**
951  * Helper function that determines if channel is an HTTP POST.
952  *
953  * @param aChannel
954  *        The channel to test
955  *
956  * @return True if channel is an HTTP post.
957  */
958 bool ChannelIsPost(nsIChannel* aChannel);
959 
960 /**
961  * Convenience functions for verifying nsIURI schemes. These functions simply
962  * wrap aURI->SchemeIs(), but specify the protocol as part of the function name.
963  */
964 
965 bool SchemeIsHTTP(nsIURI* aURI);
966 bool SchemeIsHTTPS(nsIURI* aURI);
967 bool SchemeIsJavascript(nsIURI* aURI);
968 bool SchemeIsChrome(nsIURI* aURI);
969 bool SchemeIsAbout(nsIURI* aURI);
970 bool SchemeIsBlob(nsIURI* aURI);
971 bool SchemeIsFile(nsIURI* aURI);
972 bool SchemeIsData(nsIURI* aURI);
973 bool SchemeIsViewSource(nsIURI* aURI);
974 bool SchemeIsResource(nsIURI* aURI);
975 bool SchemeIsFTP(nsIURI* aURI);
976 }  // namespace net
977 }  // namespace mozilla
978 
979 /**
980  * Returns true if the |aInput| in is part of the root domain of |aHost|.
981  * For example, if |aInput| is "www.mozilla.org", and we pass in
982  * "mozilla.org" as |aHost|, this will return true.  It would return false
983  * the other way around.
984  *
985  * @param aInput The host to be analyzed.
986  * @param aHost  The host to compare to.
987  */
988 nsresult NS_HasRootDomain(const nsACString& aInput, const nsACString& aHost,
989                           bool* aResult);
990 
991 #endif  // !nsNetUtil_h__
992