1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:set ts=4 sw=4 sts=4 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_inl
8 #define nsNetUtil_inl
9
10 #include "mozilla/Services.h"
11
12 #include "nsComponentManagerUtils.h"
13 #include "nsIBufferedStreams.h"
14 #include "nsIChannel.h"
15 #include "nsIFile.h"
16 #include "nsIFileStreams.h"
17 #include "nsIFileURL.h"
18 #include "nsIHttpChannel.h"
19 #include "nsIInputStreamChannel.h"
20 #include "nsIIOService.h"
21 #include "nsINestedURI.h"
22 #include "nsINode.h"
23 #include "nsIProtocolHandler.h"
24 #include "nsIStandardURL.h"
25 #include "nsIStreamLoader.h"
26 #include "nsIIncrementalStreamLoader.h"
27 #include "nsIURI.h"
28 #include "nsIURIWithPrincipal.h"
29 #include "nsIWritablePropertyBag2.h"
30 #include "nsNetCID.h"
31 #include "nsStringStream.h"
32
33 #ifdef MOZILLA_INTERNAL_API
34 // Don't allow functions that end up in nsNetUtil.cpp to be inlined out.
35 #define INLINE_IF_EXTERN MOZ_NEVER_INLINE
36 #else
37 // Make sure that functions included via nsNetUtil.h don't get multiply defined.
38 #define INLINE_IF_EXTERN MOZ_ALWAYS_INLINE
39 #endif
40
41 #ifdef MOZILLA_INTERNAL_API
42
43 INLINE_IF_EXTERN already_AddRefed<nsIIOService>
do_GetIOService(nsresult * error)44 do_GetIOService(nsresult *error /* = 0 */)
45 {
46 nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
47 if (error)
48 *error = io ? NS_OK : NS_ERROR_FAILURE;
49 return io.forget();
50 }
51
52 INLINE_IF_EXTERN already_AddRefed<nsINetUtil>
do_GetNetUtil(nsresult * error)53 do_GetNetUtil(nsresult *error /* = 0 */)
54 {
55 nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
56 nsCOMPtr<nsINetUtil> util;
57 if (io)
58 util = do_QueryInterface(io);
59
60 if (error)
61 *error = !!util ? NS_OK : NS_ERROR_FAILURE;
62 return util.forget();
63 }
64
65 #else
66
67 INLINE_IF_EXTERN const nsGetServiceByContractIDWithError
do_GetIOService(nsresult * error)68 do_GetIOService(nsresult *error /* = 0 */)
69 {
70 return nsGetServiceByContractIDWithError(NS_IOSERVICE_CONTRACTID, error);
71 }
72
73 INLINE_IF_EXTERN const nsGetServiceByContractIDWithError
do_GetNetUtil(nsresult * error)74 do_GetNetUtil(nsresult *error /* = 0 */)
75 {
76 return do_GetIOService(error);
77 }
78 #endif
79
80 // private little helper function... don't call this directly!
81 MOZ_ALWAYS_INLINE nsresult
net_EnsureIOService(nsIIOService ** ios,nsCOMPtr<nsIIOService> & grip)82 net_EnsureIOService(nsIIOService **ios, nsCOMPtr<nsIIOService> &grip)
83 {
84 nsresult rv = NS_OK;
85 if (!*ios) {
86 grip = do_GetIOService(&rv);
87 *ios = grip;
88 }
89 return rv;
90 }
91
92 INLINE_IF_EXTERN nsresult
NS_URIChainHasFlags(nsIURI * uri,uint32_t flags,bool * result)93 NS_URIChainHasFlags(nsIURI *uri,
94 uint32_t flags,
95 bool *result)
96 {
97 nsresult rv;
98 nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
99 NS_ENSURE_SUCCESS(rv, rv);
100
101 return util->URIChainHasFlags(uri, flags, result);
102 }
103
104 INLINE_IF_EXTERN nsresult
NS_NewURI(nsIURI ** result,const nsACString & spec,const char * charset,nsIURI * baseURI,nsIIOService * ioService)105 NS_NewURI(nsIURI **result,
106 const nsACString &spec,
107 const char *charset /* = nullptr */,
108 nsIURI *baseURI /* = nullptr */,
109 nsIIOService *ioService /* = nullptr */) // pass in nsIIOService to optimize callers
110 {
111 nsresult rv;
112 nsCOMPtr<nsIIOService> grip;
113 rv = net_EnsureIOService(&ioService, grip);
114 if (ioService)
115 rv = ioService->NewURI(spec, charset, baseURI, result);
116 return rv;
117 }
118
119 INLINE_IF_EXTERN nsresult
NS_NewURI(nsIURI ** result,const nsAString & spec,const char * charset,nsIURI * baseURI,nsIIOService * ioService)120 NS_NewURI(nsIURI **result,
121 const nsAString &spec,
122 const char *charset /* = nullptr */,
123 nsIURI *baseURI /* = nullptr */,
124 nsIIOService *ioService /* = nullptr */) // pass in nsIIOService to optimize callers
125 {
126 return NS_NewURI(result, NS_ConvertUTF16toUTF8(spec), charset, baseURI, ioService);
127 }
128
129 INLINE_IF_EXTERN nsresult
NS_NewURI(nsIURI ** result,const char * spec,nsIURI * baseURI,nsIIOService * ioService)130 NS_NewURI(nsIURI **result,
131 const char *spec,
132 nsIURI *baseURI /* = nullptr */,
133 nsIIOService *ioService /* = nullptr */) // pass in nsIIOService to optimize callers
134 {
135 return NS_NewURI(result, nsDependentCString(spec), nullptr, baseURI, ioService);
136 }
137
138 INLINE_IF_EXTERN nsresult
NS_NewFileURI(nsIURI ** result,nsIFile * spec,nsIIOService * ioService)139 NS_NewFileURI(nsIURI **result,
140 nsIFile *spec,
141 nsIIOService *ioService /* = nullptr */) // pass in nsIIOService to optimize callers
142 {
143 nsresult rv;
144 nsCOMPtr<nsIIOService> grip;
145 rv = net_EnsureIOService(&ioService, grip);
146 if (ioService)
147 rv = ioService->NewFileURI(spec, result);
148 return rv;
149 }
150
151 INLINE_IF_EXTERN nsresult
NS_NewChannelInternal(nsIChannel ** outChannel,nsIURI * aUri,nsINode * aLoadingNode,nsIPrincipal * aLoadingPrincipal,nsIPrincipal * aTriggeringPrincipal,nsSecurityFlags aSecurityFlags,nsContentPolicyType aContentPolicyType,nsILoadGroup * aLoadGroup,nsIInterfaceRequestor * aCallbacks,nsLoadFlags aLoadFlags,nsIIOService * aIoService)152 NS_NewChannelInternal(nsIChannel **outChannel,
153 nsIURI *aUri,
154 nsINode *aLoadingNode,
155 nsIPrincipal *aLoadingPrincipal,
156 nsIPrincipal *aTriggeringPrincipal,
157 nsSecurityFlags aSecurityFlags,
158 nsContentPolicyType aContentPolicyType,
159 nsILoadGroup *aLoadGroup /* = nullptr */,
160 nsIInterfaceRequestor *aCallbacks /* = nullptr */,
161 nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
162 nsIIOService *aIoService /* = nullptr */)
163 {
164 NS_ENSURE_ARG_POINTER(outChannel);
165
166 nsCOMPtr<nsIIOService> grip;
167 nsresult rv = net_EnsureIOService(&aIoService, grip);
168 NS_ENSURE_SUCCESS(rv, rv);
169
170 nsCOMPtr<nsIChannel> channel;
171 rv = aIoService->NewChannelFromURI2(
172 aUri,
173 aLoadingNode ?
174 aLoadingNode->AsDOMNode() : nullptr,
175 aLoadingPrincipal,
176 aTriggeringPrincipal,
177 aSecurityFlags,
178 aContentPolicyType,
179 getter_AddRefs(channel));
180 NS_ENSURE_SUCCESS(rv, rv);
181
182 if (aLoadGroup) {
183 rv = channel->SetLoadGroup(aLoadGroup);
184 NS_ENSURE_SUCCESS(rv, rv);
185 }
186
187 if (aCallbacks) {
188 rv = channel->SetNotificationCallbacks(aCallbacks);
189 NS_ENSURE_SUCCESS(rv, rv);
190 }
191
192 if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
193 // Retain the LOAD_REPLACE load flag if set.
194 nsLoadFlags normalLoadFlags = 0;
195 channel->GetLoadFlags(&normalLoadFlags);
196 rv = channel->SetLoadFlags(aLoadFlags | (normalLoadFlags & nsIChannel::LOAD_REPLACE));
197 NS_ENSURE_SUCCESS(rv, rv);
198 }
199
200 channel.forget(outChannel);
201 return NS_OK;
202 }
203
204 INLINE_IF_EXTERN nsresult
NS_NewChannelInternal(nsIChannel ** outChannel,nsIURI * aUri,nsILoadInfo * aLoadInfo,nsILoadGroup * aLoadGroup,nsIInterfaceRequestor * aCallbacks,nsLoadFlags aLoadFlags,nsIIOService * aIoService)205 NS_NewChannelInternal(nsIChannel **outChannel,
206 nsIURI *aUri,
207 nsILoadInfo *aLoadInfo,
208 nsILoadGroup *aLoadGroup /* = nullptr */,
209 nsIInterfaceRequestor *aCallbacks /* = nullptr */,
210 nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
211 nsIIOService *aIoService /* = nullptr */)
212 {
213 // NS_NewChannelInternal is mostly called for channel redirects. We should allow
214 // the creation of a channel even if the original channel did not have a loadinfo
215 // attached.
216 NS_ENSURE_ARG_POINTER(outChannel);
217
218 nsCOMPtr<nsIIOService> grip;
219 nsresult rv = net_EnsureIOService(&aIoService, grip);
220 NS_ENSURE_SUCCESS(rv, rv);
221
222 nsCOMPtr<nsIChannel> channel;
223 rv = aIoService->NewChannelFromURIWithLoadInfo(
224 aUri,
225 aLoadInfo,
226 getter_AddRefs(channel));
227 NS_ENSURE_SUCCESS(rv, rv);
228
229 if (aLoadGroup) {
230 rv = channel->SetLoadGroup(aLoadGroup);
231 NS_ENSURE_SUCCESS(rv, rv);
232 }
233
234 if (aCallbacks) {
235 rv = channel->SetNotificationCallbacks(aCallbacks);
236 NS_ENSURE_SUCCESS(rv, rv);
237 }
238
239 if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
240 // Retain the LOAD_REPLACE load flag if set.
241 nsLoadFlags normalLoadFlags = 0;
242 channel->GetLoadFlags(&normalLoadFlags);
243 rv = channel->SetLoadFlags(aLoadFlags | (normalLoadFlags & nsIChannel::LOAD_REPLACE));
244 NS_ENSURE_SUCCESS(rv, rv);
245 }
246
247 channel.forget(outChannel);
248 return NS_OK;
249 }
250
251 INLINE_IF_EXTERN nsresult /* NS_NewChannelPrincipal */
NS_NewChannel(nsIChannel ** outChannel,nsIURI * aUri,nsIPrincipal * aLoadingPrincipal,nsSecurityFlags aSecurityFlags,nsContentPolicyType aContentPolicyType,nsILoadGroup * aLoadGroup,nsIInterfaceRequestor * aCallbacks,nsLoadFlags aLoadFlags,nsIIOService * aIoService)252 NS_NewChannel(nsIChannel **outChannel,
253 nsIURI *aUri,
254 nsIPrincipal *aLoadingPrincipal,
255 nsSecurityFlags aSecurityFlags,
256 nsContentPolicyType aContentPolicyType,
257 nsILoadGroup *aLoadGroup /* = nullptr */,
258 nsIInterfaceRequestor *aCallbacks /* = nullptr */,
259 nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
260 nsIIOService *aIoService /* = nullptr */)
261 {
262 return NS_NewChannelInternal(outChannel,
263 aUri,
264 nullptr, // aLoadingNode,
265 aLoadingPrincipal,
266 nullptr, // aTriggeringPrincipal
267 aSecurityFlags,
268 aContentPolicyType,
269 aLoadGroup,
270 aCallbacks,
271 aLoadFlags,
272 aIoService);
273 }
274
275 INLINE_IF_EXTERN nsresult
NS_NewStreamLoader(nsIStreamLoader ** result,nsIStreamLoaderObserver * observer,nsIRequestObserver * requestObserver)276 NS_NewStreamLoader(nsIStreamLoader **result,
277 nsIStreamLoaderObserver *observer,
278 nsIRequestObserver *requestObserver /* = nullptr */)
279 {
280 nsresult rv;
281 nsCOMPtr<nsIStreamLoader> loader =
282 do_CreateInstance(NS_STREAMLOADER_CONTRACTID, &rv);
283 if (NS_SUCCEEDED(rv)) {
284 rv = loader->Init(observer, requestObserver);
285 if (NS_SUCCEEDED(rv)) {
286 *result = nullptr;
287 loader.swap(*result);
288 }
289 }
290 return rv;
291 }
292
293 INLINE_IF_EXTERN nsresult
NS_NewLocalFileInputStream(nsIInputStream ** result,nsIFile * file,int32_t ioFlags,int32_t perm,int32_t behaviorFlags)294 NS_NewLocalFileInputStream(nsIInputStream **result,
295 nsIFile *file,
296 int32_t ioFlags /* = -1 */,
297 int32_t perm /* = -1 */,
298 int32_t behaviorFlags /* = 0 */)
299 {
300 nsresult rv;
301 nsCOMPtr<nsIFileInputStream> in =
302 do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv);
303 if (NS_SUCCEEDED(rv)) {
304 rv = in->Init(file, ioFlags, perm, behaviorFlags);
305 if (NS_SUCCEEDED(rv))
306 in.forget(result);
307 }
308 return rv;
309 }
310
311 INLINE_IF_EXTERN nsresult
NS_NewLocalFileOutputStream(nsIOutputStream ** result,nsIFile * file,int32_t ioFlags,int32_t perm,int32_t behaviorFlags)312 NS_NewLocalFileOutputStream(nsIOutputStream **result,
313 nsIFile *file,
314 int32_t ioFlags /* = -1 */,
315 int32_t perm /* = -1 */,
316 int32_t behaviorFlags /* = 0 */)
317 {
318 nsresult rv;
319 nsCOMPtr<nsIFileOutputStream> out =
320 do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
321 if (NS_SUCCEEDED(rv)) {
322 rv = out->Init(file, ioFlags, perm, behaviorFlags);
323 if (NS_SUCCEEDED(rv))
324 out.forget(result);
325 }
326 return rv;
327 }
328
329 INLINE_IF_EXTERN MOZ_MUST_USE nsresult
NS_NewBufferedInputStream(nsIInputStream ** result,nsIInputStream * str,uint32_t bufferSize)330 NS_NewBufferedInputStream(nsIInputStream **result,
331 nsIInputStream *str,
332 uint32_t bufferSize)
333 {
334 nsresult rv;
335 nsCOMPtr<nsIBufferedInputStream> in =
336 do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv);
337 if (NS_SUCCEEDED(rv)) {
338 rv = in->Init(str, bufferSize);
339 if (NS_SUCCEEDED(rv)) {
340 in.forget(result);
341 }
342 }
343 return rv;
344 }
345
346 INLINE_IF_EXTERN nsresult
NS_NewPostDataStream(nsIInputStream ** result,bool isFile,const nsACString & data)347 NS_NewPostDataStream(nsIInputStream **result,
348 bool isFile,
349 const nsACString &data)
350 {
351 nsresult rv;
352
353 if (isFile) {
354 nsCOMPtr<nsIFile> file;
355 nsCOMPtr<nsIInputStream> fileStream;
356
357 rv = NS_NewNativeLocalFile(data, false, getter_AddRefs(file));
358 if (NS_SUCCEEDED(rv)) {
359 rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file);
360 if (NS_SUCCEEDED(rv)) {
361 // wrap the file stream with a buffered input stream
362 rv = NS_NewBufferedInputStream(result, fileStream, 8192);
363 }
364 }
365 return rv;
366 }
367
368 // otherwise, create a string stream for the data (copies)
369 nsCOMPtr<nsIStringInputStream> stream
370 (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv));
371 if (NS_FAILED(rv))
372 return rv;
373
374 rv = stream->SetData(data.BeginReading(), data.Length());
375 if (NS_FAILED(rv))
376 return rv;
377
378 stream.forget(result);
379 return NS_OK;
380 }
381
382 INLINE_IF_EXTERN bool
NS_IsOffline()383 NS_IsOffline()
384 {
385 bool offline = true;
386 bool connectivity = true;
387 nsCOMPtr<nsIIOService> ios = do_GetIOService();
388 if (ios) {
389 ios->GetOffline(&offline);
390 ios->GetConnectivity(&connectivity);
391 }
392 return offline || !connectivity;
393 }
394
395 #endif // nsNetUtil_inl
396