1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/base/public/nsNetUtil.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2402 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim:set ts=4 sw=4 sts=4 et cin: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef nsNetUtil_h__ 1.11 +#define nsNetUtil_h__ 1.12 + 1.13 +#include "nsError.h" 1.14 +#include "nsNetCID.h" 1.15 +#include "nsStringGlue.h" 1.16 +#include "nsMemory.h" 1.17 +#include "nsCOMPtr.h" 1.18 +#include "prio.h" // for read/write flags, permissions, etc. 1.19 +#include "nsHashKeys.h" 1.20 + 1.21 +#include "plstr.h" 1.22 +#include "nsIURI.h" 1.23 +#include "nsIStandardURL.h" 1.24 +#include "nsIURLParser.h" 1.25 +#include "nsIUUIDGenerator.h" 1.26 +#include "nsIInputStream.h" 1.27 +#include "nsIOutputStream.h" 1.28 +#include "nsISafeOutputStream.h" 1.29 +#include "nsIStreamListener.h" 1.30 +#include "nsIRequestObserverProxy.h" 1.31 +#include "nsISimpleStreamListener.h" 1.32 +#include "nsILoadGroup.h" 1.33 +#include "nsIInterfaceRequestor.h" 1.34 +#include "nsIInterfaceRequestorUtils.h" 1.35 +#include "nsIIOService.h" 1.36 +#include "nsIServiceManager.h" 1.37 +#include "nsIChannel.h" 1.38 +#include "nsChannelProperties.h" 1.39 +#include "nsIInputStreamChannel.h" 1.40 +#include "nsITransport.h" 1.41 +#include "nsIStreamTransportService.h" 1.42 +#include "nsIHttpChannel.h" 1.43 +#include "nsIDownloader.h" 1.44 +#include "nsIStreamLoader.h" 1.45 +#include "nsIUnicharStreamLoader.h" 1.46 +#include "nsIPipe.h" 1.47 +#include "nsIProtocolHandler.h" 1.48 +#include "nsIFileProtocolHandler.h" 1.49 +#include "nsIStringStream.h" 1.50 +#include "nsIFile.h" 1.51 +#include "nsIFileStreams.h" 1.52 +#include "nsIFileURL.h" 1.53 +#include "nsIProtocolProxyService.h" 1.54 +#include "nsIProxyInfo.h" 1.55 +#include "nsIFileStreams.h" 1.56 +#include "nsIBufferedStreams.h" 1.57 +#include "nsIInputStreamPump.h" 1.58 +#include "nsIAsyncStreamCopier.h" 1.59 +#include "nsIPersistentProperties2.h" 1.60 +#include "nsISyncStreamListener.h" 1.61 +#include "nsInterfaceRequestorAgg.h" 1.62 +#include "nsINetUtil.h" 1.63 +#include "nsIURIWithPrincipal.h" 1.64 +#include "nsIAuthPrompt.h" 1.65 +#include "nsIAuthPrompt2.h" 1.66 +#include "nsIAuthPromptAdapterFactory.h" 1.67 +#include "nsComponentManagerUtils.h" 1.68 +#include "nsServiceManagerUtils.h" 1.69 +#include "nsINestedURI.h" 1.70 +#include "nsIMutable.h" 1.71 +#include "nsIPropertyBag2.h" 1.72 +#include "nsIWritablePropertyBag2.h" 1.73 +#include "nsIIDNService.h" 1.74 +#include "nsIChannelEventSink.h" 1.75 +#include "nsIChannelPolicy.h" 1.76 +#include "nsISocketProviderService.h" 1.77 +#include "nsISocketProvider.h" 1.78 +#include "nsIRedirectChannelRegistrar.h" 1.79 +#include "nsIMIMEHeaderParam.h" 1.80 +#include "nsILoadContext.h" 1.81 +#include "mozilla/Services.h" 1.82 +#include "nsIPrivateBrowsingChannel.h" 1.83 +#include "mozIApplicationClearPrivateDataParams.h" 1.84 +#include "nsIOfflineCacheUpdate.h" 1.85 +#include "nsIContentSniffer.h" 1.86 +#include "nsCategoryCache.h" 1.87 +#include "nsStringStream.h" 1.88 +#include "nsIViewSourceChannel.h" 1.89 + 1.90 +#include <limits> 1.91 + 1.92 +#ifdef MOZILLA_INTERNAL_API 1.93 + 1.94 +#include "nsReadableUtils.h" 1.95 + 1.96 +inline already_AddRefed<nsIIOService> 1.97 +do_GetIOService(nsresult* error = 0) 1.98 +{ 1.99 + nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService(); 1.100 + if (error) 1.101 + *error = io ? NS_OK : NS_ERROR_FAILURE; 1.102 + return io.forget(); 1.103 +} 1.104 + 1.105 +inline already_AddRefed<nsINetUtil> 1.106 +do_GetNetUtil(nsresult *error = 0) 1.107 +{ 1.108 + nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService(); 1.109 + nsCOMPtr<nsINetUtil> util; 1.110 + if (io) 1.111 + util = do_QueryInterface(io); 1.112 + 1.113 + if (error) 1.114 + *error = !!util ? NS_OK : NS_ERROR_FAILURE; 1.115 + return util.forget(); 1.116 +} 1.117 +#else 1.118 +// Helper, to simplify getting the I/O service. 1.119 +inline const nsGetServiceByContractIDWithError 1.120 +do_GetIOService(nsresult* error = 0) 1.121 +{ 1.122 + return nsGetServiceByContractIDWithError(NS_IOSERVICE_CONTRACTID, error); 1.123 +} 1.124 + 1.125 +// An alias to do_GetIOService 1.126 +inline const nsGetServiceByContractIDWithError 1.127 +do_GetNetUtil(nsresult* error = 0) 1.128 +{ 1.129 + return do_GetIOService(error); 1.130 +} 1.131 +#endif 1.132 + 1.133 +// private little helper function... don't call this directly! 1.134 +inline nsresult 1.135 +net_EnsureIOService(nsIIOService **ios, nsCOMPtr<nsIIOService> &grip) 1.136 +{ 1.137 + nsresult rv = NS_OK; 1.138 + if (!*ios) { 1.139 + grip = do_GetIOService(&rv); 1.140 + *ios = grip; 1.141 + } 1.142 + return rv; 1.143 +} 1.144 + 1.145 +inline nsresult 1.146 +NS_NewURI(nsIURI **result, 1.147 + const nsACString &spec, 1.148 + const char *charset = nullptr, 1.149 + nsIURI *baseURI = nullptr, 1.150 + nsIIOService *ioService = nullptr) // pass in nsIIOService to optimize callers 1.151 +{ 1.152 + nsresult rv; 1.153 + nsCOMPtr<nsIIOService> grip; 1.154 + rv = net_EnsureIOService(&ioService, grip); 1.155 + if (ioService) 1.156 + rv = ioService->NewURI(spec, charset, baseURI, result); 1.157 + return rv; 1.158 +} 1.159 + 1.160 +inline nsresult 1.161 +NS_NewURI(nsIURI* *result, 1.162 + const nsAString& spec, 1.163 + const char *charset = nullptr, 1.164 + nsIURI* baseURI = nullptr, 1.165 + nsIIOService* ioService = nullptr) // pass in nsIIOService to optimize callers 1.166 +{ 1.167 + return NS_NewURI(result, NS_ConvertUTF16toUTF8(spec), charset, baseURI, ioService); 1.168 +} 1.169 + 1.170 +inline nsresult 1.171 +NS_NewURI(nsIURI* *result, 1.172 + const char *spec, 1.173 + nsIURI* baseURI = nullptr, 1.174 + nsIIOService* ioService = nullptr) // pass in nsIIOService to optimize callers 1.175 +{ 1.176 + return NS_NewURI(result, nsDependentCString(spec), nullptr, baseURI, ioService); 1.177 +} 1.178 + 1.179 +inline nsresult 1.180 +NS_NewFileURI(nsIURI* *result, 1.181 + nsIFile* spec, 1.182 + nsIIOService* ioService = nullptr) // pass in nsIIOService to optimize callers 1.183 +{ 1.184 + nsresult rv; 1.185 + nsCOMPtr<nsIIOService> grip; 1.186 + rv = net_EnsureIOService(&ioService, grip); 1.187 + if (ioService) 1.188 + rv = ioService->NewFileURI(spec, result); 1.189 + return rv; 1.190 +} 1.191 + 1.192 +inline nsresult 1.193 +NS_NewChannel(nsIChannel **result, 1.194 + nsIURI *uri, 1.195 + nsIIOService *ioService = nullptr, // pass in nsIIOService to optimize callers 1.196 + nsILoadGroup *loadGroup = nullptr, 1.197 + nsIInterfaceRequestor *callbacks = nullptr, 1.198 + uint32_t loadFlags = nsIRequest::LOAD_NORMAL, 1.199 + nsIChannelPolicy *channelPolicy = nullptr) 1.200 +{ 1.201 + nsresult rv; 1.202 + nsCOMPtr<nsIIOService> grip; 1.203 + rv = net_EnsureIOService(&ioService, grip); 1.204 + if (ioService) { 1.205 + nsCOMPtr<nsIChannel> chan; 1.206 + rv = ioService->NewChannelFromURI(uri, getter_AddRefs(chan)); 1.207 + if (NS_SUCCEEDED(rv)) { 1.208 + if (loadGroup) { 1.209 + rv = chan->SetLoadGroup(loadGroup); 1.210 + } 1.211 + if (callbacks) { 1.212 + nsresult tmp = chan->SetNotificationCallbacks(callbacks); 1.213 + if (NS_FAILED(tmp)) { 1.214 + rv = tmp; 1.215 + } 1.216 + } 1.217 + if (loadFlags != nsIRequest::LOAD_NORMAL) { 1.218 + // Retain the LOAD_REPLACE load flag if set. 1.219 + nsLoadFlags normalLoadFlags = 0; 1.220 + chan->GetLoadFlags(&normalLoadFlags); 1.221 + nsresult tmp = chan->SetLoadFlags(loadFlags | 1.222 + (normalLoadFlags & 1.223 + nsIChannel::LOAD_REPLACE)); 1.224 + if (NS_FAILED(tmp)) { 1.225 + rv = tmp; 1.226 + } 1.227 + } 1.228 + if (channelPolicy) { 1.229 + nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(chan); 1.230 + if (props) { 1.231 + props->SetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY, 1.232 + channelPolicy); 1.233 + } 1.234 + } 1.235 + if (NS_SUCCEEDED(rv)) 1.236 + chan.forget(result); 1.237 + } 1.238 + } 1.239 + return rv; 1.240 +} 1.241 + 1.242 +// Use this function with CAUTION. It creates a stream that blocks when you 1.243 +// Read() from it and blocking the UI thread is a bad idea. If you don't want 1.244 +// to implement a full blown asynchronous consumer (via nsIStreamListener) look 1.245 +// at nsIStreamLoader instead. 1.246 +inline nsresult 1.247 +NS_OpenURI(nsIInputStream **result, 1.248 + nsIURI *uri, 1.249 + nsIIOService *ioService = nullptr, // pass in nsIIOService to optimize callers 1.250 + nsILoadGroup *loadGroup = nullptr, 1.251 + nsIInterfaceRequestor *callbacks = nullptr, 1.252 + uint32_t loadFlags = nsIRequest::LOAD_NORMAL, 1.253 + nsIChannel **channelOut = nullptr) 1.254 +{ 1.255 + nsresult rv; 1.256 + nsCOMPtr<nsIChannel> channel; 1.257 + rv = NS_NewChannel(getter_AddRefs(channel), uri, ioService, 1.258 + loadGroup, callbacks, loadFlags); 1.259 + if (NS_SUCCEEDED(rv)) { 1.260 + nsIInputStream *stream; 1.261 + rv = channel->Open(&stream); 1.262 + if (NS_SUCCEEDED(rv)) { 1.263 + *result = stream; 1.264 + if (channelOut) { 1.265 + *channelOut = nullptr; 1.266 + channel.swap(*channelOut); 1.267 + } 1.268 + } 1.269 + } 1.270 + return rv; 1.271 +} 1.272 + 1.273 +inline nsresult 1.274 +NS_OpenURI(nsIStreamListener *listener, 1.275 + nsISupports *context, 1.276 + nsIURI *uri, 1.277 + nsIIOService *ioService = nullptr, // pass in nsIIOService to optimize callers 1.278 + nsILoadGroup *loadGroup = nullptr, 1.279 + nsIInterfaceRequestor *callbacks = nullptr, 1.280 + uint32_t loadFlags = nsIRequest::LOAD_NORMAL) 1.281 +{ 1.282 + nsresult rv; 1.283 + nsCOMPtr<nsIChannel> channel; 1.284 + rv = NS_NewChannel(getter_AddRefs(channel), uri, ioService, 1.285 + loadGroup, callbacks, loadFlags); 1.286 + if (NS_SUCCEEDED(rv)) 1.287 + rv = channel->AsyncOpen(listener, context); 1.288 + return rv; 1.289 +} 1.290 + 1.291 +inline nsresult 1.292 +NS_MakeAbsoluteURI(nsACString &result, 1.293 + const nsACString &spec, 1.294 + nsIURI *baseURI) 1.295 +{ 1.296 + nsresult rv; 1.297 + if (!baseURI) { 1.298 + NS_WARNING("It doesn't make sense to not supply a base URI"); 1.299 + result = spec; 1.300 + rv = NS_OK; 1.301 + } 1.302 + else if (spec.IsEmpty()) 1.303 + rv = baseURI->GetSpec(result); 1.304 + else 1.305 + rv = baseURI->Resolve(spec, result); 1.306 + return rv; 1.307 +} 1.308 + 1.309 +inline nsresult 1.310 +NS_MakeAbsoluteURI(char **result, 1.311 + const char *spec, 1.312 + nsIURI *baseURI) 1.313 +{ 1.314 + nsresult rv; 1.315 + nsAutoCString resultBuf; 1.316 + rv = NS_MakeAbsoluteURI(resultBuf, nsDependentCString(spec), baseURI); 1.317 + if (NS_SUCCEEDED(rv)) { 1.318 + *result = ToNewCString(resultBuf); 1.319 + if (!*result) 1.320 + rv = NS_ERROR_OUT_OF_MEMORY; 1.321 + } 1.322 + return rv; 1.323 +} 1.324 + 1.325 +inline nsresult 1.326 +NS_MakeAbsoluteURI(nsAString &result, 1.327 + const nsAString &spec, 1.328 + nsIURI *baseURI) 1.329 +{ 1.330 + nsresult rv; 1.331 + if (!baseURI) { 1.332 + NS_WARNING("It doesn't make sense to not supply a base URI"); 1.333 + result = spec; 1.334 + rv = NS_OK; 1.335 + } 1.336 + else { 1.337 + nsAutoCString resultBuf; 1.338 + if (spec.IsEmpty()) 1.339 + rv = baseURI->GetSpec(resultBuf); 1.340 + else 1.341 + rv = baseURI->Resolve(NS_ConvertUTF16toUTF8(spec), resultBuf); 1.342 + if (NS_SUCCEEDED(rv)) 1.343 + CopyUTF8toUTF16(resultBuf, result); 1.344 + } 1.345 + return rv; 1.346 +} 1.347 + 1.348 +/** 1.349 + * This function is a helper function to get a scheme's default port. 1.350 + */ 1.351 +inline int32_t 1.352 +NS_GetDefaultPort(const char *scheme, 1.353 + nsIIOService* ioService = nullptr) 1.354 +{ 1.355 + nsresult rv; 1.356 + 1.357 + nsCOMPtr<nsIIOService> grip; 1.358 + net_EnsureIOService(&ioService, grip); 1.359 + if (!ioService) 1.360 + return -1; 1.361 + 1.362 + nsCOMPtr<nsIProtocolHandler> handler; 1.363 + rv = ioService->GetProtocolHandler(scheme, getter_AddRefs(handler)); 1.364 + if (NS_FAILED(rv)) 1.365 + return -1; 1.366 + int32_t port; 1.367 + rv = handler->GetDefaultPort(&port); 1.368 + return NS_SUCCEEDED(rv) ? port : -1; 1.369 +} 1.370 + 1.371 +/** 1.372 + * This function is a helper function to apply the ToAscii conversion 1.373 + * to a string 1.374 + */ 1.375 +inline bool 1.376 +NS_StringToACE(const nsACString &idn, nsACString &result) 1.377 +{ 1.378 + nsCOMPtr<nsIIDNService> idnSrv = do_GetService(NS_IDNSERVICE_CONTRACTID); 1.379 + if (!idnSrv) 1.380 + return false; 1.381 + nsresult rv = idnSrv->ConvertUTF8toACE(idn, result); 1.382 + if (NS_FAILED(rv)) 1.383 + return false; 1.384 + 1.385 + return true; 1.386 +} 1.387 + 1.388 +/** 1.389 + * This function is a helper function to get a protocol's default port if the 1.390 + * URI does not specify a port explicitly. Returns -1 if this protocol has no 1.391 + * concept of ports or if there was an error getting the port. 1.392 + */ 1.393 +inline int32_t 1.394 +NS_GetRealPort(nsIURI* aURI) 1.395 +{ 1.396 + int32_t port; 1.397 + nsresult rv = aURI->GetPort(&port); 1.398 + if (NS_FAILED(rv)) 1.399 + return -1; 1.400 + 1.401 + if (port != -1) 1.402 + return port; // explicitly specified 1.403 + 1.404 + // Otherwise, we have to get the default port from the protocol handler 1.405 + 1.406 + // Need the scheme first 1.407 + nsAutoCString scheme; 1.408 + rv = aURI->GetScheme(scheme); 1.409 + if (NS_FAILED(rv)) 1.410 + return -1; 1.411 + 1.412 + return NS_GetDefaultPort(scheme.get()); 1.413 +} 1.414 + 1.415 +inline nsresult 1.416 +NS_NewInputStreamChannel(nsIChannel **result, 1.417 + nsIURI *uri, 1.418 + nsIInputStream *stream, 1.419 + const nsACString &contentType, 1.420 + const nsACString *contentCharset) 1.421 +{ 1.422 + nsresult rv; 1.423 + nsCOMPtr<nsIInputStreamChannel> isc = 1.424 + do_CreateInstance(NS_INPUTSTREAMCHANNEL_CONTRACTID, &rv); 1.425 + if (NS_FAILED(rv)) 1.426 + return rv; 1.427 + rv = isc->SetURI(uri); 1.428 + nsresult tmp = isc->SetContentStream(stream); 1.429 + if (NS_FAILED(tmp)) { 1.430 + rv = tmp; 1.431 + } 1.432 + if (NS_FAILED(rv)) 1.433 + return rv; 1.434 + nsCOMPtr<nsIChannel> chan = do_QueryInterface(isc, &rv); 1.435 + if (NS_FAILED(rv)) 1.436 + return rv; 1.437 + if (!contentType.IsEmpty()) 1.438 + rv = chan->SetContentType(contentType); 1.439 + if (contentCharset && !contentCharset->IsEmpty()) { 1.440 + tmp = chan->SetContentCharset(*contentCharset); 1.441 + if (NS_FAILED(tmp)) { 1.442 + rv = tmp; 1.443 + } 1.444 + } 1.445 + if (NS_SUCCEEDED(rv)) { 1.446 + *result = nullptr; 1.447 + chan.swap(*result); 1.448 + } 1.449 + return rv; 1.450 +} 1.451 + 1.452 +inline nsresult 1.453 +NS_NewInputStreamChannel(nsIChannel **result, 1.454 + nsIURI *uri, 1.455 + nsIInputStream *stream, 1.456 + const nsACString &contentType = EmptyCString()) 1.457 +{ 1.458 + return NS_NewInputStreamChannel(result, uri, stream, contentType, nullptr); 1.459 +} 1.460 + 1.461 +inline nsresult 1.462 +NS_NewInputStreamChannel(nsIChannel **result, 1.463 + nsIURI *uri, 1.464 + nsIInputStream *stream, 1.465 + const nsACString &contentType, 1.466 + const nsACString &contentCharset) 1.467 +{ 1.468 + return NS_NewInputStreamChannel(result, uri, stream, contentType, 1.469 + &contentCharset); 1.470 +} 1.471 + 1.472 +inline nsresult 1.473 +NS_NewInputStreamChannel(nsIChannel **result, 1.474 + nsIURI *uri, 1.475 + const nsAString &data, 1.476 + const nsACString &contentType, 1.477 + bool isSrcdocChannel = false) 1.478 +{ 1.479 + 1.480 + nsresult rv; 1.481 + 1.482 + nsCOMPtr<nsIStringInputStream> stream; 1.483 + stream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv); 1.484 + NS_ENSURE_SUCCESS(rv, rv); 1.485 + 1.486 +#ifdef MOZILLA_INTERNAL_API 1.487 + uint32_t len; 1.488 + char* utf8Bytes = ToNewUTF8String(data, &len); 1.489 + rv = stream->AdoptData(utf8Bytes, len); 1.490 +#else 1.491 + char* utf8Bytes = ToNewUTF8String(data); 1.492 + rv = stream->AdoptData(utf8Bytes, strlen(utf8Bytes)); 1.493 +#endif 1.494 + 1.495 + nsCOMPtr<nsIChannel> chan; 1.496 + 1.497 + rv = NS_NewInputStreamChannel(getter_AddRefs(chan), uri, stream, 1.498 + contentType, NS_LITERAL_CSTRING("UTF-8")); 1.499 + NS_ENSURE_SUCCESS(rv, rv); 1.500 + 1.501 + if (isSrcdocChannel) { 1.502 + nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(chan); 1.503 + NS_ENSURE_TRUE(inStrmChan, NS_ERROR_FAILURE); 1.504 + inStrmChan->SetSrcdocData(data); 1.505 + } 1.506 + 1.507 + *result = nullptr; 1.508 + chan.swap(*result); 1.509 + 1.510 + return NS_OK; 1.511 +} 1.512 + 1.513 +inline nsresult 1.514 +NS_NewInputStreamPump(nsIInputStreamPump **result, 1.515 + nsIInputStream *stream, 1.516 + int64_t streamPos = int64_t(-1), 1.517 + int64_t streamLen = int64_t(-1), 1.518 + uint32_t segsize = 0, 1.519 + uint32_t segcount = 0, 1.520 + bool closeWhenDone = false) 1.521 +{ 1.522 + nsresult rv; 1.523 + nsCOMPtr<nsIInputStreamPump> pump = 1.524 + do_CreateInstance(NS_INPUTSTREAMPUMP_CONTRACTID, &rv); 1.525 + if (NS_SUCCEEDED(rv)) { 1.526 + rv = pump->Init(stream, streamPos, streamLen, 1.527 + segsize, segcount, closeWhenDone); 1.528 + if (NS_SUCCEEDED(rv)) { 1.529 + *result = nullptr; 1.530 + pump.swap(*result); 1.531 + } 1.532 + } 1.533 + return rv; 1.534 +} 1.535 + 1.536 +// NOTE: you will need to specify whether or not your streams are buffered 1.537 +// (i.e., do they implement ReadSegments/WriteSegments). the default 1.538 +// assumption of TRUE for both streams might not be right for you! 1.539 +inline nsresult 1.540 +NS_NewAsyncStreamCopier(nsIAsyncStreamCopier **result, 1.541 + nsIInputStream *source, 1.542 + nsIOutputStream *sink, 1.543 + nsIEventTarget *target, 1.544 + bool sourceBuffered = true, 1.545 + bool sinkBuffered = true, 1.546 + uint32_t chunkSize = 0, 1.547 + bool closeSource = true, 1.548 + bool closeSink = true) 1.549 +{ 1.550 + nsresult rv; 1.551 + nsCOMPtr<nsIAsyncStreamCopier> copier = 1.552 + do_CreateInstance(NS_ASYNCSTREAMCOPIER_CONTRACTID, &rv); 1.553 + if (NS_SUCCEEDED(rv)) { 1.554 + rv = copier->Init(source, sink, target, sourceBuffered, sinkBuffered, 1.555 + chunkSize, closeSource, closeSink); 1.556 + if (NS_SUCCEEDED(rv)) { 1.557 + *result = nullptr; 1.558 + copier.swap(*result); 1.559 + } 1.560 + } 1.561 + return rv; 1.562 +} 1.563 + 1.564 +inline nsresult 1.565 +NS_NewLoadGroup(nsILoadGroup **result, 1.566 + nsIRequestObserver *obs) 1.567 +{ 1.568 + nsresult rv; 1.569 + nsCOMPtr<nsILoadGroup> group = 1.570 + do_CreateInstance(NS_LOADGROUP_CONTRACTID, &rv); 1.571 + if (NS_SUCCEEDED(rv)) { 1.572 + rv = group->SetGroupObserver(obs); 1.573 + if (NS_SUCCEEDED(rv)) { 1.574 + *result = nullptr; 1.575 + group.swap(*result); 1.576 + } 1.577 + } 1.578 + return rv; 1.579 +} 1.580 + 1.581 +inline nsresult 1.582 +NS_NewDownloader(nsIStreamListener **result, 1.583 + nsIDownloadObserver *observer, 1.584 + nsIFile *downloadLocation = nullptr) 1.585 +{ 1.586 + nsresult rv; 1.587 + nsCOMPtr<nsIDownloader> downloader = 1.588 + do_CreateInstance(NS_DOWNLOADER_CONTRACTID, &rv); 1.589 + if (NS_SUCCEEDED(rv)) { 1.590 + rv = downloader->Init(observer, downloadLocation); 1.591 + if (NS_SUCCEEDED(rv)) 1.592 + NS_ADDREF(*result = downloader); 1.593 + } 1.594 + return rv; 1.595 +} 1.596 + 1.597 +inline nsresult 1.598 +NS_NewStreamLoader(nsIStreamLoader **result, 1.599 + nsIStreamLoaderObserver *observer) 1.600 +{ 1.601 + nsresult rv; 1.602 + nsCOMPtr<nsIStreamLoader> loader = 1.603 + do_CreateInstance(NS_STREAMLOADER_CONTRACTID, &rv); 1.604 + if (NS_SUCCEEDED(rv)) { 1.605 + rv = loader->Init(observer); 1.606 + if (NS_SUCCEEDED(rv)) { 1.607 + *result = nullptr; 1.608 + loader.swap(*result); 1.609 + } 1.610 + } 1.611 + return rv; 1.612 +} 1.613 + 1.614 +inline nsresult 1.615 +NS_NewStreamLoader(nsIStreamLoader **result, 1.616 + nsIURI *uri, 1.617 + nsIStreamLoaderObserver *observer, 1.618 + nsISupports *context = nullptr, 1.619 + nsILoadGroup *loadGroup = nullptr, 1.620 + nsIInterfaceRequestor *callbacks = nullptr, 1.621 + uint32_t loadFlags = nsIRequest::LOAD_NORMAL, 1.622 + nsIURI *referrer = nullptr) 1.623 +{ 1.624 + nsresult rv; 1.625 + nsCOMPtr<nsIChannel> channel; 1.626 + rv = NS_NewChannel(getter_AddRefs(channel), 1.627 + uri, 1.628 + nullptr, 1.629 + loadGroup, 1.630 + callbacks, 1.631 + loadFlags); 1.632 + if (NS_SUCCEEDED(rv)) { 1.633 + nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); 1.634 + if (httpChannel) 1.635 + httpChannel->SetReferrer(referrer); 1.636 + rv = NS_NewStreamLoader(result, observer); 1.637 + if (NS_SUCCEEDED(rv)) 1.638 + rv = channel->AsyncOpen(*result, context); 1.639 + } 1.640 + return rv; 1.641 +} 1.642 + 1.643 +inline nsresult 1.644 +NS_NewUnicharStreamLoader(nsIUnicharStreamLoader **result, 1.645 + nsIUnicharStreamLoaderObserver *observer) 1.646 +{ 1.647 + nsresult rv; 1.648 + nsCOMPtr<nsIUnicharStreamLoader> loader = 1.649 + do_CreateInstance(NS_UNICHARSTREAMLOADER_CONTRACTID, &rv); 1.650 + if (NS_SUCCEEDED(rv)) { 1.651 + rv = loader->Init(observer); 1.652 + if (NS_SUCCEEDED(rv)) { 1.653 + *result = nullptr; 1.654 + loader.swap(*result); 1.655 + } 1.656 + } 1.657 + return rv; 1.658 +} 1.659 + 1.660 +inline nsresult 1.661 +NS_NewSyncStreamListener(nsIStreamListener **result, 1.662 + nsIInputStream **stream) 1.663 +{ 1.664 + nsresult rv; 1.665 + nsCOMPtr<nsISyncStreamListener> listener = 1.666 + do_CreateInstance(NS_SYNCSTREAMLISTENER_CONTRACTID, &rv); 1.667 + if (NS_SUCCEEDED(rv)) { 1.668 + rv = listener->GetInputStream(stream); 1.669 + if (NS_SUCCEEDED(rv)) 1.670 + NS_ADDREF(*result = listener); // cannot use nsCOMPtr::swap 1.671 + } 1.672 + return rv; 1.673 +} 1.674 + 1.675 +/** 1.676 + * Implement the nsIChannel::Open(nsIInputStream**) method using the channel's 1.677 + * AsyncOpen method. 1.678 + * 1.679 + * NOTE: Reading from the returned nsIInputStream may spin the current 1.680 + * thread's event queue, which could result in any event being processed. 1.681 + */ 1.682 +inline nsresult 1.683 +NS_ImplementChannelOpen(nsIChannel *channel, 1.684 + nsIInputStream **result) 1.685 +{ 1.686 + nsCOMPtr<nsIStreamListener> listener; 1.687 + nsCOMPtr<nsIInputStream> stream; 1.688 + nsresult rv = NS_NewSyncStreamListener(getter_AddRefs(listener), 1.689 + getter_AddRefs(stream)); 1.690 + if (NS_SUCCEEDED(rv)) { 1.691 + rv = channel->AsyncOpen(listener, nullptr); 1.692 + if (NS_SUCCEEDED(rv)) { 1.693 + uint64_t n; 1.694 + // block until the initial response is received or an error occurs. 1.695 + rv = stream->Available(&n); 1.696 + if (NS_SUCCEEDED(rv)) { 1.697 + *result = nullptr; 1.698 + stream.swap(*result); 1.699 + } 1.700 + } 1.701 + } 1.702 + return rv; 1.703 +} 1.704 + 1.705 +inline nsresult 1.706 +NS_NewRequestObserverProxy(nsIRequestObserver **result, 1.707 + nsIRequestObserver *observer, 1.708 + nsISupports *context) 1.709 +{ 1.710 + nsresult rv; 1.711 + nsCOMPtr<nsIRequestObserverProxy> proxy = 1.712 + do_CreateInstance(NS_REQUESTOBSERVERPROXY_CONTRACTID, &rv); 1.713 + if (NS_SUCCEEDED(rv)) { 1.714 + rv = proxy->Init(observer, context); 1.715 + if (NS_SUCCEEDED(rv)) 1.716 + NS_ADDREF(*result = proxy); // cannot use nsCOMPtr::swap 1.717 + } 1.718 + return rv; 1.719 +} 1.720 + 1.721 +inline nsresult 1.722 +NS_NewSimpleStreamListener(nsIStreamListener **result, 1.723 + nsIOutputStream *sink, 1.724 + nsIRequestObserver *observer = nullptr) 1.725 +{ 1.726 + nsresult rv; 1.727 + nsCOMPtr<nsISimpleStreamListener> listener = 1.728 + do_CreateInstance(NS_SIMPLESTREAMLISTENER_CONTRACTID, &rv); 1.729 + if (NS_SUCCEEDED(rv)) { 1.730 + rv = listener->Init(sink, observer); 1.731 + if (NS_SUCCEEDED(rv)) 1.732 + NS_ADDREF(*result = listener); // cannot use nsCOMPtr::swap 1.733 + } 1.734 + return rv; 1.735 +} 1.736 + 1.737 +inline nsresult 1.738 +NS_CheckPortSafety(int32_t port, 1.739 + const char *scheme, 1.740 + nsIIOService *ioService = nullptr) 1.741 +{ 1.742 + nsresult rv; 1.743 + nsCOMPtr<nsIIOService> grip; 1.744 + rv = net_EnsureIOService(&ioService, grip); 1.745 + if (ioService) { 1.746 + bool allow; 1.747 + rv = ioService->AllowPort(port, scheme, &allow); 1.748 + if (NS_SUCCEEDED(rv) && !allow) { 1.749 + NS_WARNING("port blocked"); 1.750 + rv = NS_ERROR_PORT_ACCESS_NOT_ALLOWED; 1.751 + } 1.752 + } 1.753 + return rv; 1.754 +} 1.755 + 1.756 +// Determine if this URI is using a safe port. 1.757 +inline nsresult 1.758 +NS_CheckPortSafety(nsIURI *uri) { 1.759 + int32_t port; 1.760 + nsresult rv = uri->GetPort(&port); 1.761 + if (NS_FAILED(rv) || port == -1) // port undefined or default-valued 1.762 + return NS_OK; 1.763 + nsAutoCString scheme; 1.764 + uri->GetScheme(scheme); 1.765 + return NS_CheckPortSafety(port, scheme.get()); 1.766 +} 1.767 + 1.768 +inline nsresult 1.769 +NS_NewProxyInfo(const nsACString &type, 1.770 + const nsACString &host, 1.771 + int32_t port, 1.772 + uint32_t flags, 1.773 + nsIProxyInfo **result) 1.774 +{ 1.775 + nsresult rv; 1.776 + nsCOMPtr<nsIProtocolProxyService> pps = 1.777 + do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv); 1.778 + if (NS_SUCCEEDED(rv)) 1.779 + rv = pps->NewProxyInfo(type, host, port, flags, UINT32_MAX, nullptr, 1.780 + result); 1.781 + return rv; 1.782 +} 1.783 + 1.784 +inline nsresult 1.785 +NS_GetFileProtocolHandler(nsIFileProtocolHandler **result, 1.786 + nsIIOService *ioService = nullptr) 1.787 +{ 1.788 + nsresult rv; 1.789 + nsCOMPtr<nsIIOService> grip; 1.790 + rv = net_EnsureIOService(&ioService, grip); 1.791 + if (ioService) { 1.792 + nsCOMPtr<nsIProtocolHandler> handler; 1.793 + rv = ioService->GetProtocolHandler("file", getter_AddRefs(handler)); 1.794 + if (NS_SUCCEEDED(rv)) 1.795 + rv = CallQueryInterface(handler, result); 1.796 + } 1.797 + return rv; 1.798 +} 1.799 + 1.800 +inline nsresult 1.801 +NS_GetFileFromURLSpec(const nsACString &inURL, 1.802 + nsIFile **result, 1.803 + nsIIOService *ioService = nullptr) 1.804 +{ 1.805 + nsresult rv; 1.806 + nsCOMPtr<nsIFileProtocolHandler> fileHandler; 1.807 + rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService); 1.808 + if (NS_SUCCEEDED(rv)) 1.809 + rv = fileHandler->GetFileFromURLSpec(inURL, result); 1.810 + return rv; 1.811 +} 1.812 + 1.813 +inline nsresult 1.814 +NS_GetURLSpecFromFile(nsIFile *file, 1.815 + nsACString &url, 1.816 + nsIIOService *ioService = nullptr) 1.817 +{ 1.818 + nsresult rv; 1.819 + nsCOMPtr<nsIFileProtocolHandler> fileHandler; 1.820 + rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService); 1.821 + if (NS_SUCCEEDED(rv)) 1.822 + rv = fileHandler->GetURLSpecFromFile(file, url); 1.823 + return rv; 1.824 +} 1.825 + 1.826 +/** 1.827 + * Converts the nsIFile to the corresponding URL string. 1.828 + * Should only be called on files which are not directories, 1.829 + * is otherwise identical to NS_GetURLSpecFromFile, but is 1.830 + * usually more efficient. 1.831 + * Warning: this restriction may not be enforced at runtime! 1.832 + */ 1.833 +inline nsresult 1.834 +NS_GetURLSpecFromActualFile(nsIFile *file, 1.835 + nsACString &url, 1.836 + nsIIOService *ioService = nullptr) 1.837 +{ 1.838 + nsresult rv; 1.839 + nsCOMPtr<nsIFileProtocolHandler> fileHandler; 1.840 + rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService); 1.841 + if (NS_SUCCEEDED(rv)) 1.842 + rv = fileHandler->GetURLSpecFromActualFile(file, url); 1.843 + return rv; 1.844 +} 1.845 + 1.846 +/** 1.847 + * Converts the nsIFile to the corresponding URL string. 1.848 + * Should only be called on files which are directories, 1.849 + * is otherwise identical to NS_GetURLSpecFromFile, but is 1.850 + * usually more efficient. 1.851 + * Warning: this restriction may not be enforced at runtime! 1.852 + */ 1.853 +inline nsresult 1.854 +NS_GetURLSpecFromDir(nsIFile *file, 1.855 + nsACString &url, 1.856 + nsIIOService *ioService = nullptr) 1.857 +{ 1.858 + nsresult rv; 1.859 + nsCOMPtr<nsIFileProtocolHandler> fileHandler; 1.860 + rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService); 1.861 + if (NS_SUCCEEDED(rv)) 1.862 + rv = fileHandler->GetURLSpecFromDir(file, url); 1.863 + return rv; 1.864 +} 1.865 + 1.866 +/** 1.867 + * Obtains the referrer for a given channel. This first tries to obtain the 1.868 + * referrer from the property docshell.internalReferrer, and if that doesn't 1.869 + * work and the channel is an nsIHTTPChannel, we check it's referrer property. 1.870 + * 1.871 + * @returns NS_ERROR_NOT_AVAILABLE if no referrer is available. 1.872 + */ 1.873 +inline nsresult 1.874 +NS_GetReferrerFromChannel(nsIChannel *channel, 1.875 + nsIURI **referrer) 1.876 +{ 1.877 + nsresult rv = NS_ERROR_NOT_AVAILABLE; 1.878 + *referrer = nullptr; 1.879 + 1.880 + nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(channel)); 1.881 + if (props) { 1.882 + // We have to check for a property on a property bag because the 1.883 + // referrer may be empty for security reasons (for example, when loading 1.884 + // an http page with an https referrer). 1.885 + rv = props->GetPropertyAsInterface(NS_LITERAL_STRING("docshell.internalReferrer"), 1.886 + NS_GET_IID(nsIURI), 1.887 + reinterpret_cast<void **>(referrer)); 1.888 + if (NS_FAILED(rv)) 1.889 + *referrer = nullptr; 1.890 + } 1.891 + 1.892 + // if that didn't work, we can still try to get the referrer from the 1.893 + // nsIHttpChannel (if we can QI to it) 1.894 + if (!(*referrer)) { 1.895 + nsCOMPtr<nsIHttpChannel> chan(do_QueryInterface(channel)); 1.896 + if (chan) { 1.897 + rv = chan->GetReferrer(referrer); 1.898 + if (NS_FAILED(rv)) 1.899 + *referrer = nullptr; 1.900 + } 1.901 + } 1.902 + return rv; 1.903 +} 1.904 + 1.905 +inline nsresult 1.906 +NS_ParseContentType(const nsACString &rawContentType, 1.907 + nsCString &contentType, 1.908 + nsCString &contentCharset) 1.909 +{ 1.910 + // contentCharset is left untouched if not present in rawContentType 1.911 + nsresult rv; 1.912 + nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv); 1.913 + NS_ENSURE_SUCCESS(rv, rv); 1.914 + nsCString charset; 1.915 + bool hadCharset; 1.916 + rv = util->ParseContentType(rawContentType, charset, &hadCharset, 1.917 + contentType); 1.918 + if (NS_SUCCEEDED(rv) && hadCharset) 1.919 + contentCharset = charset; 1.920 + return rv; 1.921 +} 1.922 + 1.923 +inline nsresult 1.924 +NS_ExtractCharsetFromContentType(const nsACString &rawContentType, 1.925 + nsCString &contentCharset, 1.926 + bool *hadCharset, 1.927 + int32_t *charsetStart, 1.928 + int32_t *charsetEnd) 1.929 +{ 1.930 + // contentCharset is left untouched if not present in rawContentType 1.931 + nsresult rv; 1.932 + nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv); 1.933 + NS_ENSURE_SUCCESS(rv, rv); 1.934 + 1.935 + return util->ExtractCharsetFromContentType(rawContentType, 1.936 + contentCharset, 1.937 + charsetStart, 1.938 + charsetEnd, 1.939 + hadCharset); 1.940 +} 1.941 + 1.942 +inline nsresult 1.943 +NS_NewLocalFileInputStream(nsIInputStream **result, 1.944 + nsIFile *file, 1.945 + int32_t ioFlags = -1, 1.946 + int32_t perm = -1, 1.947 + int32_t behaviorFlags = 0) 1.948 +{ 1.949 + nsresult rv; 1.950 + nsCOMPtr<nsIFileInputStream> in = 1.951 + do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv); 1.952 + if (NS_SUCCEEDED(rv)) { 1.953 + rv = in->Init(file, ioFlags, perm, behaviorFlags); 1.954 + if (NS_SUCCEEDED(rv)) 1.955 + in.forget(result); 1.956 + } 1.957 + return rv; 1.958 +} 1.959 + 1.960 +inline nsresult 1.961 +NS_NewPartialLocalFileInputStream(nsIInputStream **result, 1.962 + nsIFile *file, 1.963 + uint64_t offset, 1.964 + uint64_t length, 1.965 + int32_t ioFlags = -1, 1.966 + int32_t perm = -1, 1.967 + int32_t behaviorFlags = 0) 1.968 +{ 1.969 + nsresult rv; 1.970 + nsCOMPtr<nsIPartialFileInputStream> in = 1.971 + do_CreateInstance(NS_PARTIALLOCALFILEINPUTSTREAM_CONTRACTID, &rv); 1.972 + if (NS_SUCCEEDED(rv)) { 1.973 + rv = in->Init(file, offset, length, ioFlags, perm, behaviorFlags); 1.974 + if (NS_SUCCEEDED(rv)) 1.975 + rv = CallQueryInterface(in, result); 1.976 + } 1.977 + return rv; 1.978 +} 1.979 + 1.980 +inline nsresult 1.981 +NS_NewLocalFileOutputStream(nsIOutputStream **result, 1.982 + nsIFile *file, 1.983 + int32_t ioFlags = -1, 1.984 + int32_t perm = -1, 1.985 + int32_t behaviorFlags = 0) 1.986 +{ 1.987 + nsresult rv; 1.988 + nsCOMPtr<nsIFileOutputStream> out = 1.989 + do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &rv); 1.990 + if (NS_SUCCEEDED(rv)) { 1.991 + rv = out->Init(file, ioFlags, perm, behaviorFlags); 1.992 + if (NS_SUCCEEDED(rv)) 1.993 + out.forget(result); 1.994 + } 1.995 + return rv; 1.996 +} 1.997 + 1.998 +// returns a file output stream which can be QI'ed to nsISafeOutputStream. 1.999 +inline nsresult 1.1000 +NS_NewAtomicFileOutputStream(nsIOutputStream **result, 1.1001 + nsIFile *file, 1.1002 + int32_t ioFlags = -1, 1.1003 + int32_t perm = -1, 1.1004 + int32_t behaviorFlags = 0) 1.1005 +{ 1.1006 + nsresult rv; 1.1007 + nsCOMPtr<nsIFileOutputStream> out = 1.1008 + do_CreateInstance(NS_ATOMICLOCALFILEOUTPUTSTREAM_CONTRACTID, &rv); 1.1009 + if (NS_SUCCEEDED(rv)) { 1.1010 + rv = out->Init(file, ioFlags, perm, behaviorFlags); 1.1011 + if (NS_SUCCEEDED(rv)) 1.1012 + out.forget(result); 1.1013 + } 1.1014 + return rv; 1.1015 +} 1.1016 + 1.1017 +// returns a file output stream which can be QI'ed to nsISafeOutputStream. 1.1018 +inline nsresult 1.1019 +NS_NewSafeLocalFileOutputStream(nsIOutputStream **result, 1.1020 + nsIFile *file, 1.1021 + int32_t ioFlags = -1, 1.1022 + int32_t perm = -1, 1.1023 + int32_t behaviorFlags = 0) 1.1024 +{ 1.1025 + nsresult rv; 1.1026 + nsCOMPtr<nsIFileOutputStream> out = 1.1027 + do_CreateInstance(NS_SAFELOCALFILEOUTPUTSTREAM_CONTRACTID, &rv); 1.1028 + if (NS_SUCCEEDED(rv)) { 1.1029 + rv = out->Init(file, ioFlags, perm, behaviorFlags); 1.1030 + if (NS_SUCCEEDED(rv)) 1.1031 + out.forget(result); 1.1032 + } 1.1033 + return rv; 1.1034 +} 1.1035 + 1.1036 +inline nsresult 1.1037 +NS_NewLocalFileStream(nsIFileStream **result, 1.1038 + nsIFile *file, 1.1039 + int32_t ioFlags = -1, 1.1040 + int32_t perm = -1, 1.1041 + int32_t behaviorFlags = 0) 1.1042 +{ 1.1043 + nsresult rv; 1.1044 + nsCOMPtr<nsIFileStream> stream = 1.1045 + do_CreateInstance(NS_LOCALFILESTREAM_CONTRACTID, &rv); 1.1046 + if (NS_SUCCEEDED(rv)) { 1.1047 + rv = stream->Init(file, ioFlags, perm, behaviorFlags); 1.1048 + if (NS_SUCCEEDED(rv)) 1.1049 + stream.forget(result); 1.1050 + } 1.1051 + return rv; 1.1052 +} 1.1053 + 1.1054 +// returns the input end of a pipe. the output end of the pipe 1.1055 +// is attached to the original stream. data from the original 1.1056 +// stream is read into the pipe on a background thread. 1.1057 +inline nsresult 1.1058 +NS_BackgroundInputStream(nsIInputStream **result, 1.1059 + nsIInputStream *stream, 1.1060 + uint32_t segmentSize = 0, 1.1061 + uint32_t segmentCount = 0) 1.1062 +{ 1.1063 + nsresult rv; 1.1064 + nsCOMPtr<nsIStreamTransportService> sts = 1.1065 + do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); 1.1066 + if (NS_SUCCEEDED(rv)) { 1.1067 + nsCOMPtr<nsITransport> inTransport; 1.1068 + rv = sts->CreateInputTransport(stream, int64_t(-1), int64_t(-1), 1.1069 + true, getter_AddRefs(inTransport)); 1.1070 + if (NS_SUCCEEDED(rv)) 1.1071 + rv = inTransport->OpenInputStream(nsITransport::OPEN_BLOCKING, 1.1072 + segmentSize, segmentCount, 1.1073 + result); 1.1074 + } 1.1075 + return rv; 1.1076 +} 1.1077 + 1.1078 +// returns the output end of a pipe. the input end of the pipe 1.1079 +// is attached to the original stream. data written to the pipe 1.1080 +// is copied to the original stream on a background thread. 1.1081 +inline nsresult 1.1082 +NS_BackgroundOutputStream(nsIOutputStream **result, 1.1083 + nsIOutputStream *stream, 1.1084 + uint32_t segmentSize = 0, 1.1085 + uint32_t segmentCount = 0) 1.1086 +{ 1.1087 + nsresult rv; 1.1088 + nsCOMPtr<nsIStreamTransportService> sts = 1.1089 + do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); 1.1090 + if (NS_SUCCEEDED(rv)) { 1.1091 + nsCOMPtr<nsITransport> inTransport; 1.1092 + rv = sts->CreateOutputTransport(stream, int64_t(-1), int64_t(-1), 1.1093 + true, getter_AddRefs(inTransport)); 1.1094 + if (NS_SUCCEEDED(rv)) 1.1095 + rv = inTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING, 1.1096 + segmentSize, segmentCount, 1.1097 + result); 1.1098 + } 1.1099 + return rv; 1.1100 +} 1.1101 + 1.1102 +MOZ_WARN_UNUSED_RESULT inline nsresult 1.1103 +NS_NewBufferedInputStream(nsIInputStream **result, 1.1104 + nsIInputStream *str, 1.1105 + uint32_t bufferSize) 1.1106 +{ 1.1107 + nsresult rv; 1.1108 + nsCOMPtr<nsIBufferedInputStream> in = 1.1109 + do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv); 1.1110 + if (NS_SUCCEEDED(rv)) { 1.1111 + rv = in->Init(str, bufferSize); 1.1112 + if (NS_SUCCEEDED(rv)) 1.1113 + NS_ADDREF(*result = in); // cannot use nsCOMPtr::swap 1.1114 + } 1.1115 + return rv; 1.1116 +} 1.1117 + 1.1118 +// note: the resulting stream can be QI'ed to nsISafeOutputStream iff the 1.1119 +// provided stream supports it. 1.1120 +inline nsresult 1.1121 +NS_NewBufferedOutputStream(nsIOutputStream **result, 1.1122 + nsIOutputStream *str, 1.1123 + uint32_t bufferSize) 1.1124 +{ 1.1125 + nsresult rv; 1.1126 + nsCOMPtr<nsIBufferedOutputStream> out = 1.1127 + do_CreateInstance(NS_BUFFEREDOUTPUTSTREAM_CONTRACTID, &rv); 1.1128 + if (NS_SUCCEEDED(rv)) { 1.1129 + rv = out->Init(str, bufferSize); 1.1130 + if (NS_SUCCEEDED(rv)) 1.1131 + NS_ADDREF(*result = out); // cannot use nsCOMPtr::swap 1.1132 + } 1.1133 + return rv; 1.1134 +} 1.1135 + 1.1136 +/** 1.1137 + * Attempts to buffer a given output stream. If this fails, it returns the 1.1138 + * passed-in output stream. 1.1139 + * 1.1140 + * @param aOutputStream 1.1141 + * The output stream we want to buffer. This cannot be null. 1.1142 + * @param aBufferSize 1.1143 + * The size of the buffer for the buffered output stream. 1.1144 + * @returns an nsIOutputStream that is buffered with the specified buffer size, 1.1145 + * or is aOutputStream if creating the new buffered stream failed. 1.1146 + */ 1.1147 +inline already_AddRefed<nsIOutputStream> 1.1148 +NS_BufferOutputStream(nsIOutputStream *aOutputStream, 1.1149 + uint32_t aBufferSize) 1.1150 +{ 1.1151 + NS_ASSERTION(aOutputStream, "No output stream given!"); 1.1152 + 1.1153 + nsCOMPtr<nsIOutputStream> bos; 1.1154 + nsresult rv = NS_NewBufferedOutputStream(getter_AddRefs(bos), aOutputStream, 1.1155 + aBufferSize); 1.1156 + if (NS_SUCCEEDED(rv)) 1.1157 + return bos.forget(); 1.1158 + 1.1159 + bos = aOutputStream; 1.1160 + return bos.forget(); 1.1161 +} 1.1162 + 1.1163 +// returns an input stream compatible with nsIUploadChannel::SetUploadStream() 1.1164 +inline nsresult 1.1165 +NS_NewPostDataStream(nsIInputStream **result, 1.1166 + bool isFile, 1.1167 + const nsACString &data) 1.1168 +{ 1.1169 + nsresult rv; 1.1170 + 1.1171 + if (isFile) { 1.1172 + nsCOMPtr<nsIFile> file; 1.1173 + nsCOMPtr<nsIInputStream> fileStream; 1.1174 + 1.1175 + rv = NS_NewNativeLocalFile(data, false, getter_AddRefs(file)); 1.1176 + if (NS_SUCCEEDED(rv)) { 1.1177 + rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file); 1.1178 + if (NS_SUCCEEDED(rv)) { 1.1179 + // wrap the file stream with a buffered input stream 1.1180 + rv = NS_NewBufferedInputStream(result, fileStream, 8192); 1.1181 + } 1.1182 + } 1.1183 + return rv; 1.1184 + } 1.1185 + 1.1186 + // otherwise, create a string stream for the data (copies) 1.1187 + nsCOMPtr<nsIStringInputStream> stream 1.1188 + (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv)); 1.1189 + if (NS_FAILED(rv)) 1.1190 + return rv; 1.1191 + 1.1192 + rv = stream->SetData(data.BeginReading(), data.Length()); 1.1193 + if (NS_FAILED(rv)) 1.1194 + return rv; 1.1195 + 1.1196 + NS_ADDREF(*result = stream); 1.1197 + return NS_OK; 1.1198 +} 1.1199 + 1.1200 +inline nsresult 1.1201 +NS_ReadInputStreamToBuffer(nsIInputStream *aInputStream, 1.1202 + void** aDest, 1.1203 + uint32_t aCount) 1.1204 +{ 1.1205 + nsresult rv; 1.1206 + 1.1207 + if (!*aDest) { 1.1208 + *aDest = malloc(aCount); 1.1209 + if (!*aDest) 1.1210 + return NS_ERROR_OUT_OF_MEMORY; 1.1211 + } 1.1212 + 1.1213 + char * p = reinterpret_cast<char*>(*aDest); 1.1214 + uint32_t bytesRead; 1.1215 + uint32_t totalRead = 0; 1.1216 + while (1) { 1.1217 + rv = aInputStream->Read(p + totalRead, aCount - totalRead, &bytesRead); 1.1218 + if (!NS_SUCCEEDED(rv)) 1.1219 + return rv; 1.1220 + totalRead += bytesRead; 1.1221 + if (totalRead == aCount) 1.1222 + break; 1.1223 + // if Read reads 0 bytes, we've hit EOF 1.1224 + if (bytesRead == 0) 1.1225 + return NS_ERROR_UNEXPECTED; 1.1226 + } 1.1227 + return rv; 1.1228 +} 1.1229 + 1.1230 +// external code can't see fallible_t 1.1231 +#ifdef MOZILLA_INTERNAL_API 1.1232 + 1.1233 +inline nsresult 1.1234 +NS_ReadInputStreamToString(nsIInputStream *aInputStream, 1.1235 + nsACString &aDest, 1.1236 + uint32_t aCount) 1.1237 +{ 1.1238 + if (!aDest.SetLength(aCount, mozilla::fallible_t())) 1.1239 + return NS_ERROR_OUT_OF_MEMORY; 1.1240 + void* dest = aDest.BeginWriting(); 1.1241 + return NS_ReadInputStreamToBuffer(aInputStream, &dest, aCount); 1.1242 +} 1.1243 + 1.1244 +#endif 1.1245 + 1.1246 +inline nsresult 1.1247 +NS_LoadPersistentPropertiesFromURI(nsIPersistentProperties **result, 1.1248 + nsIURI *uri, 1.1249 + nsIIOService *ioService = nullptr) 1.1250 +{ 1.1251 + nsCOMPtr<nsIInputStream> in; 1.1252 + nsresult rv = NS_OpenURI(getter_AddRefs(in), uri, ioService); 1.1253 + if (NS_SUCCEEDED(rv)) { 1.1254 + nsCOMPtr<nsIPersistentProperties> properties = 1.1255 + do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID, &rv); 1.1256 + if (NS_SUCCEEDED(rv)) { 1.1257 + rv = properties->Load(in); 1.1258 + if (NS_SUCCEEDED(rv)) { 1.1259 + *result = nullptr; 1.1260 + properties.swap(*result); 1.1261 + } 1.1262 + } 1.1263 + } 1.1264 + return rv; 1.1265 +} 1.1266 + 1.1267 +inline nsresult 1.1268 +NS_LoadPersistentPropertiesFromURISpec(nsIPersistentProperties **result, 1.1269 + const nsACString &spec, 1.1270 + const char *charset = nullptr, 1.1271 + nsIURI *baseURI = nullptr, 1.1272 + nsIIOService *ioService = nullptr) 1.1273 +{ 1.1274 + nsCOMPtr<nsIURI> uri; 1.1275 + nsresult rv = 1.1276 + NS_NewURI(getter_AddRefs(uri), spec, charset, baseURI, ioService); 1.1277 + 1.1278 + if (NS_SUCCEEDED(rv)) 1.1279 + rv = NS_LoadPersistentPropertiesFromURI(result, uri, ioService); 1.1280 + 1.1281 + return rv; 1.1282 +} 1.1283 + 1.1284 +/** 1.1285 + * NS_QueryNotificationCallbacks implements the canonical algorithm for 1.1286 + * querying interfaces from a channel's notification callbacks. It first 1.1287 + * searches the channel's notificationCallbacks attribute, and if the interface 1.1288 + * is not found there, then it inspects the notificationCallbacks attribute of 1.1289 + * the channel's loadGroup. 1.1290 + * 1.1291 + * Note: templatized only because nsIWebSocketChannel is currently not an 1.1292 + * nsIChannel. 1.1293 + */ 1.1294 +template <class T> inline void 1.1295 +NS_QueryNotificationCallbacks(T *channel, 1.1296 + const nsIID &iid, 1.1297 + void **result) 1.1298 +{ 1.1299 + NS_PRECONDITION(channel, "null channel"); 1.1300 + *result = nullptr; 1.1301 + 1.1302 + nsCOMPtr<nsIInterfaceRequestor> cbs; 1.1303 + channel->GetNotificationCallbacks(getter_AddRefs(cbs)); 1.1304 + if (cbs) 1.1305 + cbs->GetInterface(iid, result); 1.1306 + if (!*result) { 1.1307 + // try load group's notification callbacks... 1.1308 + nsCOMPtr<nsILoadGroup> loadGroup; 1.1309 + channel->GetLoadGroup(getter_AddRefs(loadGroup)); 1.1310 + if (loadGroup) { 1.1311 + loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs)); 1.1312 + if (cbs) 1.1313 + cbs->GetInterface(iid, result); 1.1314 + } 1.1315 + } 1.1316 +} 1.1317 + 1.1318 +// template helper: 1.1319 +// Note: "class C" templatized only because nsIWebSocketChannel is currently not 1.1320 +// an nsIChannel. 1.1321 + 1.1322 +template <class C, class T> inline void 1.1323 +NS_QueryNotificationCallbacks(C *channel, 1.1324 + nsCOMPtr<T> &result) 1.1325 +{ 1.1326 + NS_QueryNotificationCallbacks(channel, NS_GET_TEMPLATE_IID(T), 1.1327 + getter_AddRefs(result)); 1.1328 +} 1.1329 + 1.1330 +/** 1.1331 + * Alternate form of NS_QueryNotificationCallbacks designed for use by 1.1332 + * nsIChannel implementations. 1.1333 + */ 1.1334 +inline void 1.1335 +NS_QueryNotificationCallbacks(nsIInterfaceRequestor *callbacks, 1.1336 + nsILoadGroup *loadGroup, 1.1337 + const nsIID &iid, 1.1338 + void **result) 1.1339 +{ 1.1340 + *result = nullptr; 1.1341 + 1.1342 + if (callbacks) 1.1343 + callbacks->GetInterface(iid, result); 1.1344 + if (!*result) { 1.1345 + // try load group's notification callbacks... 1.1346 + if (loadGroup) { 1.1347 + nsCOMPtr<nsIInterfaceRequestor> cbs; 1.1348 + loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs)); 1.1349 + if (cbs) 1.1350 + cbs->GetInterface(iid, result); 1.1351 + } 1.1352 + } 1.1353 +} 1.1354 + 1.1355 +/** 1.1356 + * Returns true if channel is using Private Browsing, or false if not. 1.1357 + * Returns false if channel's callbacks don't implement nsILoadContext. 1.1358 + */ 1.1359 +inline bool 1.1360 +NS_UsePrivateBrowsing(nsIChannel *channel) 1.1361 +{ 1.1362 + bool isPrivate = false; 1.1363 + bool isOverriden = false; 1.1364 + nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(channel); 1.1365 + if (pbChannel && 1.1366 + NS_SUCCEEDED(pbChannel->IsPrivateModeOverriden(&isPrivate, &isOverriden)) && 1.1367 + isOverriden) { 1.1368 + return isPrivate; 1.1369 + } 1.1370 + nsCOMPtr<nsILoadContext> loadContext; 1.1371 + NS_QueryNotificationCallbacks(channel, loadContext); 1.1372 + return loadContext && loadContext->UsePrivateBrowsing(); 1.1373 +} 1.1374 + 1.1375 +// Constants duplicated from nsIScriptSecurityManager so we avoid having necko 1.1376 +// know about script security manager. 1.1377 +#define NECKO_NO_APP_ID 0 1.1378 +#define NECKO_UNKNOWN_APP_ID UINT32_MAX 1.1379 +// special app id reserved for separating the safebrowsing cookie 1.1380 +#define NECKO_SAFEBROWSING_APP_ID UINT32_MAX - 1 1.1381 + 1.1382 +/** 1.1383 + * Gets AppId and isInBrowserElement from channel's nsILoadContext. 1.1384 + * Returns false if error or channel's callbacks don't implement nsILoadContext. 1.1385 + */ 1.1386 +inline bool 1.1387 +NS_GetAppInfo(nsIChannel *aChannel, uint32_t *aAppID, bool *aIsInBrowserElement) 1.1388 +{ 1.1389 + nsCOMPtr<nsILoadContext> loadContext; 1.1390 + NS_QueryNotificationCallbacks(aChannel, loadContext); 1.1391 + if (!loadContext) { 1.1392 + return false; 1.1393 + } 1.1394 + 1.1395 + nsresult rv = loadContext->GetAppId(aAppID); 1.1396 + NS_ENSURE_SUCCESS(rv, false); 1.1397 + 1.1398 + rv = loadContext->GetIsInBrowserElement(aIsInBrowserElement); 1.1399 + NS_ENSURE_SUCCESS(rv, false); 1.1400 + 1.1401 + return true; 1.1402 +} 1.1403 + 1.1404 +/** 1.1405 + * Gets appId and browserOnly parameters from the TOPIC_WEB_APP_CLEAR_DATA 1.1406 + * nsIObserverService notification. Used when clearing user data or 1.1407 + * uninstalling web apps. 1.1408 + */ 1.1409 +inline nsresult 1.1410 +NS_GetAppInfoFromClearDataNotification(nsISupports *aSubject, 1.1411 + uint32_t *aAppID, bool* aBrowserOnly) 1.1412 +{ 1.1413 + nsresult rv; 1.1414 + 1.1415 + nsCOMPtr<mozIApplicationClearPrivateDataParams> 1.1416 + clearParams(do_QueryInterface(aSubject)); 1.1417 + MOZ_ASSERT(clearParams); 1.1418 + if (!clearParams) { 1.1419 + return NS_ERROR_UNEXPECTED; 1.1420 + } 1.1421 + 1.1422 + uint32_t appId; 1.1423 + rv = clearParams->GetAppId(&appId); 1.1424 + MOZ_ASSERT(NS_SUCCEEDED(rv)); 1.1425 + MOZ_ASSERT(appId != NECKO_UNKNOWN_APP_ID); 1.1426 + NS_ENSURE_SUCCESS(rv, rv); 1.1427 + if (appId == NECKO_UNKNOWN_APP_ID) { 1.1428 + return NS_ERROR_UNEXPECTED; 1.1429 + } 1.1430 + 1.1431 + bool browserOnly = false; 1.1432 + rv = clearParams->GetBrowserOnly(&browserOnly); 1.1433 + MOZ_ASSERT(NS_SUCCEEDED(rv)); 1.1434 + NS_ENSURE_SUCCESS(rv, rv); 1.1435 + 1.1436 + *aAppID = appId; 1.1437 + *aBrowserOnly = browserOnly; 1.1438 + return NS_OK; 1.1439 +} 1.1440 + 1.1441 +/** 1.1442 + * Determines whether appcache should be checked for a given URI. 1.1443 + */ 1.1444 +inline bool 1.1445 +NS_ShouldCheckAppCache(nsIURI *aURI, bool usePrivateBrowsing) 1.1446 +{ 1.1447 + if (usePrivateBrowsing) { 1.1448 + return false; 1.1449 + } 1.1450 + 1.1451 + nsCOMPtr<nsIOfflineCacheUpdateService> offlineService = 1.1452 + do_GetService("@mozilla.org/offlinecacheupdate-service;1"); 1.1453 + if (!offlineService) { 1.1454 + return false; 1.1455 + } 1.1456 + 1.1457 + bool allowed; 1.1458 + nsresult rv = offlineService->OfflineAppAllowedForURI(aURI, 1.1459 + nullptr, 1.1460 + &allowed); 1.1461 + return NS_SUCCEEDED(rv) && allowed; 1.1462 +} 1.1463 + 1.1464 +inline bool 1.1465 +NS_ShouldCheckAppCache(nsIPrincipal * aPrincipal, bool usePrivateBrowsing) 1.1466 +{ 1.1467 + if (usePrivateBrowsing) { 1.1468 + return false; 1.1469 + } 1.1470 + 1.1471 + nsCOMPtr<nsIOfflineCacheUpdateService> offlineService = 1.1472 + do_GetService("@mozilla.org/offlinecacheupdate-service;1"); 1.1473 + if (!offlineService) { 1.1474 + return false; 1.1475 + } 1.1476 + 1.1477 + bool allowed; 1.1478 + nsresult rv = offlineService->OfflineAppAllowed(aPrincipal, 1.1479 + nullptr, 1.1480 + &allowed); 1.1481 + return NS_SUCCEEDED(rv) && allowed; 1.1482 +} 1.1483 + 1.1484 +/** 1.1485 + * Wraps an nsIAuthPrompt so that it can be used as an nsIAuthPrompt2. This 1.1486 + * method is provided mainly for use by other methods in this file. 1.1487 + * 1.1488 + * *aAuthPrompt2 should be set to null before calling this function. 1.1489 + */ 1.1490 +inline void 1.1491 +NS_WrapAuthPrompt(nsIAuthPrompt *aAuthPrompt, nsIAuthPrompt2** aAuthPrompt2) 1.1492 +{ 1.1493 + nsCOMPtr<nsIAuthPromptAdapterFactory> factory = 1.1494 + do_GetService(NS_AUTHPROMPT_ADAPTER_FACTORY_CONTRACTID); 1.1495 + if (!factory) 1.1496 + return; 1.1497 + 1.1498 + NS_WARNING("Using deprecated nsIAuthPrompt"); 1.1499 + factory->CreateAdapter(aAuthPrompt, aAuthPrompt2); 1.1500 +} 1.1501 + 1.1502 +/** 1.1503 + * Gets an auth prompt from an interface requestor. This takes care of wrapping 1.1504 + * an nsIAuthPrompt so that it can be used as an nsIAuthPrompt2. 1.1505 + */ 1.1506 +inline void 1.1507 +NS_QueryAuthPrompt2(nsIInterfaceRequestor *aCallbacks, 1.1508 + nsIAuthPrompt2 **aAuthPrompt) 1.1509 +{ 1.1510 + CallGetInterface(aCallbacks, aAuthPrompt); 1.1511 + if (*aAuthPrompt) 1.1512 + return; 1.1513 + 1.1514 + // Maybe only nsIAuthPrompt is provided and we have to wrap it. 1.1515 + nsCOMPtr<nsIAuthPrompt> prompt(do_GetInterface(aCallbacks)); 1.1516 + if (!prompt) 1.1517 + return; 1.1518 + 1.1519 + NS_WrapAuthPrompt(prompt, aAuthPrompt); 1.1520 +} 1.1521 + 1.1522 +/** 1.1523 + * Gets an nsIAuthPrompt2 from a channel. Use this instead of 1.1524 + * NS_QueryNotificationCallbacks for better backwards compatibility. 1.1525 + */ 1.1526 +inline void 1.1527 +NS_QueryAuthPrompt2(nsIChannel *aChannel, 1.1528 + nsIAuthPrompt2 **aAuthPrompt) 1.1529 +{ 1.1530 + *aAuthPrompt = nullptr; 1.1531 + 1.1532 + // We want to use any auth prompt we can find on the channel's callbacks, 1.1533 + // and if that fails use the loadgroup's prompt (if any) 1.1534 + // Therefore, we can't just use NS_QueryNotificationCallbacks, because 1.1535 + // that would prefer a loadgroup's nsIAuthPrompt2 over a channel's 1.1536 + // nsIAuthPrompt. 1.1537 + nsCOMPtr<nsIInterfaceRequestor> callbacks; 1.1538 + aChannel->GetNotificationCallbacks(getter_AddRefs(callbacks)); 1.1539 + if (callbacks) { 1.1540 + NS_QueryAuthPrompt2(callbacks, aAuthPrompt); 1.1541 + if (*aAuthPrompt) 1.1542 + return; 1.1543 + } 1.1544 + 1.1545 + nsCOMPtr<nsILoadGroup> group; 1.1546 + aChannel->GetLoadGroup(getter_AddRefs(group)); 1.1547 + if (!group) 1.1548 + return; 1.1549 + 1.1550 + group->GetNotificationCallbacks(getter_AddRefs(callbacks)); 1.1551 + if (!callbacks) 1.1552 + return; 1.1553 + NS_QueryAuthPrompt2(callbacks, aAuthPrompt); 1.1554 +} 1.1555 + 1.1556 +/* template helper */ 1.1557 +template <class T> inline void 1.1558 +NS_QueryNotificationCallbacks(nsIInterfaceRequestor *callbacks, 1.1559 + nsILoadGroup *loadGroup, 1.1560 + nsCOMPtr<T> &result) 1.1561 +{ 1.1562 + NS_QueryNotificationCallbacks(callbacks, loadGroup, 1.1563 + NS_GET_TEMPLATE_IID(T), 1.1564 + getter_AddRefs(result)); 1.1565 +} 1.1566 + 1.1567 +/* template helper */ 1.1568 +template <class T> inline void 1.1569 +NS_QueryNotificationCallbacks(const nsCOMPtr<nsIInterfaceRequestor> &aCallbacks, 1.1570 + const nsCOMPtr<nsILoadGroup> &aLoadGroup, 1.1571 + nsCOMPtr<T> &aResult) 1.1572 +{ 1.1573 + NS_QueryNotificationCallbacks(aCallbacks.get(), aLoadGroup.get(), aResult); 1.1574 +} 1.1575 + 1.1576 +/* template helper */ 1.1577 +template <class T> inline void 1.1578 +NS_QueryNotificationCallbacks(const nsCOMPtr<nsIChannel> &aChannel, 1.1579 + nsCOMPtr<T> &aResult) 1.1580 +{ 1.1581 + NS_QueryNotificationCallbacks(aChannel.get(), aResult); 1.1582 +} 1.1583 + 1.1584 +/** 1.1585 + * This function returns a nsIInterfaceRequestor instance that returns the 1.1586 + * same result as NS_QueryNotificationCallbacks when queried. It is useful 1.1587 + * as the value for nsISocketTransport::securityCallbacks. 1.1588 + */ 1.1589 +inline nsresult 1.1590 +NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor *callbacks, 1.1591 + nsILoadGroup *loadGroup, 1.1592 + nsIEventTarget *target, 1.1593 + nsIInterfaceRequestor **result) 1.1594 +{ 1.1595 + nsCOMPtr<nsIInterfaceRequestor> cbs; 1.1596 + if (loadGroup) 1.1597 + loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs)); 1.1598 + return NS_NewInterfaceRequestorAggregation(callbacks, cbs, target, result); 1.1599 +} 1.1600 + 1.1601 +inline nsresult 1.1602 +NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor *callbacks, 1.1603 + nsILoadGroup *loadGroup, 1.1604 + nsIInterfaceRequestor **result) 1.1605 +{ 1.1606 + return NS_NewNotificationCallbacksAggregation(callbacks, loadGroup, nullptr, result); 1.1607 +} 1.1608 + 1.1609 +/** 1.1610 + * Helper function for testing online/offline state of the browser. 1.1611 + */ 1.1612 +inline bool 1.1613 +NS_IsOffline() 1.1614 +{ 1.1615 + bool offline = true; 1.1616 + nsCOMPtr<nsIIOService> ios = do_GetIOService(); 1.1617 + if (ios) 1.1618 + ios->GetOffline(&offline); 1.1619 + return offline; 1.1620 +} 1.1621 + 1.1622 +/** 1.1623 + * Helper functions for implementing nsINestedURI::innermostURI. 1.1624 + * 1.1625 + * Note that NS_DoImplGetInnermostURI is "private" -- call 1.1626 + * NS_ImplGetInnermostURI instead. 1.1627 + */ 1.1628 +inline nsresult 1.1629 +NS_DoImplGetInnermostURI(nsINestedURI* nestedURI, nsIURI** result) 1.1630 +{ 1.1631 + NS_PRECONDITION(nestedURI, "Must have a nested URI!"); 1.1632 + NS_PRECONDITION(!*result, "Must have null *result"); 1.1633 + 1.1634 + nsCOMPtr<nsIURI> inner; 1.1635 + nsresult rv = nestedURI->GetInnerURI(getter_AddRefs(inner)); 1.1636 + NS_ENSURE_SUCCESS(rv, rv); 1.1637 + 1.1638 + // We may need to loop here until we reach the innermost 1.1639 + // URI. 1.1640 + nsCOMPtr<nsINestedURI> nestedInner(do_QueryInterface(inner)); 1.1641 + while (nestedInner) { 1.1642 + rv = nestedInner->GetInnerURI(getter_AddRefs(inner)); 1.1643 + NS_ENSURE_SUCCESS(rv, rv); 1.1644 + nestedInner = do_QueryInterface(inner); 1.1645 + } 1.1646 + 1.1647 + // Found the innermost one if we reach here. 1.1648 + inner.swap(*result); 1.1649 + 1.1650 + return rv; 1.1651 +} 1.1652 + 1.1653 +inline nsresult 1.1654 +NS_ImplGetInnermostURI(nsINestedURI* nestedURI, nsIURI** result) 1.1655 +{ 1.1656 + // Make it safe to use swap() 1.1657 + *result = nullptr; 1.1658 + 1.1659 + return NS_DoImplGetInnermostURI(nestedURI, result); 1.1660 +} 1.1661 + 1.1662 +/** 1.1663 + * Helper function that ensures that |result| is a URI that's safe to 1.1664 + * return. If |uri| is immutable, just returns it, otherwise returns 1.1665 + * a clone. |uri| must not be null. 1.1666 + */ 1.1667 +inline nsresult 1.1668 +NS_EnsureSafeToReturn(nsIURI* uri, nsIURI** result) 1.1669 +{ 1.1670 + NS_PRECONDITION(uri, "Must have a URI"); 1.1671 + 1.1672 + // Assume mutable until told otherwise 1.1673 + bool isMutable = true; 1.1674 + nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(uri)); 1.1675 + if (mutableObj) { 1.1676 + nsresult rv = mutableObj->GetMutable(&isMutable); 1.1677 + isMutable = NS_FAILED(rv) || isMutable; 1.1678 + } 1.1679 + 1.1680 + if (!isMutable) { 1.1681 + NS_ADDREF(*result = uri); 1.1682 + return NS_OK; 1.1683 + } 1.1684 + 1.1685 + nsresult rv = uri->Clone(result); 1.1686 + if (NS_SUCCEEDED(rv) && !*result) { 1.1687 + NS_ERROR("nsIURI.clone contract was violated"); 1.1688 + return NS_ERROR_UNEXPECTED; 1.1689 + } 1.1690 + 1.1691 + return rv; 1.1692 +} 1.1693 + 1.1694 +/** 1.1695 + * Helper function that tries to set the argument URI to be immutable 1.1696 + */ 1.1697 +inline void 1.1698 +NS_TryToSetImmutable(nsIURI* uri) 1.1699 +{ 1.1700 + nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(uri)); 1.1701 + if (mutableObj) { 1.1702 + mutableObj->SetMutable(false); 1.1703 + } 1.1704 +} 1.1705 + 1.1706 +/** 1.1707 + * Helper function for calling ToImmutableURI. If all else fails, returns 1.1708 + * the input URI. The optional second arg indicates whether we had to fall 1.1709 + * back to the input URI. Passing in a null URI is ok. 1.1710 + */ 1.1711 +inline already_AddRefed<nsIURI> 1.1712 +NS_TryToMakeImmutable(nsIURI* uri, 1.1713 + nsresult* outRv = nullptr) 1.1714 +{ 1.1715 + nsresult rv; 1.1716 + nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv); 1.1717 + 1.1718 + nsCOMPtr<nsIURI> result; 1.1719 + if (NS_SUCCEEDED(rv)) { 1.1720 + NS_ASSERTION(util, "do_GetNetUtil lied"); 1.1721 + rv = util->ToImmutableURI(uri, getter_AddRefs(result)); 1.1722 + } 1.1723 + 1.1724 + if (NS_FAILED(rv)) { 1.1725 + result = uri; 1.1726 + } 1.1727 + 1.1728 + if (outRv) { 1.1729 + *outRv = rv; 1.1730 + } 1.1731 + 1.1732 + return result.forget(); 1.1733 +} 1.1734 + 1.1735 +/** 1.1736 + * Helper function for testing whether the given URI, or any of its 1.1737 + * inner URIs, has all the given protocol flags. 1.1738 + */ 1.1739 +inline nsresult 1.1740 +NS_URIChainHasFlags(nsIURI *uri, 1.1741 + uint32_t flags, 1.1742 + bool *result) 1.1743 +{ 1.1744 + nsresult rv; 1.1745 + nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv); 1.1746 + NS_ENSURE_SUCCESS(rv, rv); 1.1747 + 1.1748 + return util->URIChainHasFlags(uri, flags, result); 1.1749 +} 1.1750 + 1.1751 +/** 1.1752 + * Helper function for getting the innermost URI for a given URI. The return 1.1753 + * value could be just the object passed in if it's not a nested URI. 1.1754 + */ 1.1755 +inline already_AddRefed<nsIURI> 1.1756 +NS_GetInnermostURI(nsIURI* aURI) 1.1757 +{ 1.1758 + NS_PRECONDITION(aURI, "Must have URI"); 1.1759 + 1.1760 + nsCOMPtr<nsIURI> uri = aURI; 1.1761 + 1.1762 + nsCOMPtr<nsINestedURI> nestedURI(do_QueryInterface(uri)); 1.1763 + if (!nestedURI) { 1.1764 + return uri.forget(); 1.1765 + } 1.1766 + 1.1767 + nsresult rv = nestedURI->GetInnermostURI(getter_AddRefs(uri)); 1.1768 + if (NS_FAILED(rv)) { 1.1769 + return nullptr; 1.1770 + } 1.1771 + 1.1772 + return uri.forget(); 1.1773 +} 1.1774 + 1.1775 +/** 1.1776 + * Get the "final" URI for a channel. This is either the same as GetURI or 1.1777 + * GetOriginalURI, depending on whether this channel has 1.1778 + * nsIChanel::LOAD_REPLACE set. For channels without that flag set, the final 1.1779 + * URI is the original URI, while for ones with the flag the final URI is the 1.1780 + * channel URI. 1.1781 + */ 1.1782 +inline nsresult 1.1783 +NS_GetFinalChannelURI(nsIChannel* channel, nsIURI** uri) 1.1784 +{ 1.1785 + *uri = nullptr; 1.1786 + nsLoadFlags loadFlags = 0; 1.1787 + nsresult rv = channel->GetLoadFlags(&loadFlags); 1.1788 + NS_ENSURE_SUCCESS(rv, rv); 1.1789 + 1.1790 + if (loadFlags & nsIChannel::LOAD_REPLACE) { 1.1791 + return channel->GetURI(uri); 1.1792 + } 1.1793 + 1.1794 + return channel->GetOriginalURI(uri); 1.1795 +} 1.1796 + 1.1797 +// NS_SecurityHashURI must return the same hash value for any two URIs that 1.1798 +// compare equal according to NS_SecurityCompareURIs. Unfortunately, in the 1.1799 +// case of files, it's not clear we can do anything better than returning 1.1800 +// the schemeHash, so hashing files degenerates to storing them in a list. 1.1801 +inline uint32_t 1.1802 +NS_SecurityHashURI(nsIURI* aURI) 1.1803 +{ 1.1804 + nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI); 1.1805 + 1.1806 + nsAutoCString scheme; 1.1807 + uint32_t schemeHash = 0; 1.1808 + if (NS_SUCCEEDED(baseURI->GetScheme(scheme))) 1.1809 + schemeHash = mozilla::HashString(scheme); 1.1810 + 1.1811 + // TODO figure out how to hash file:// URIs 1.1812 + if (scheme.EqualsLiteral("file")) 1.1813 + return schemeHash; // sad face 1.1814 + 1.1815 + if (scheme.EqualsLiteral("imap") || 1.1816 + scheme.EqualsLiteral("mailbox") || 1.1817 + scheme.EqualsLiteral("news")) 1.1818 + { 1.1819 + nsAutoCString spec; 1.1820 + uint32_t specHash; 1.1821 + nsresult res = baseURI->GetSpec(spec); 1.1822 + if (NS_SUCCEEDED(res)) 1.1823 + specHash = mozilla::HashString(spec); 1.1824 + else 1.1825 + specHash = static_cast<uint32_t>(res); 1.1826 + return specHash; 1.1827 + } 1.1828 + 1.1829 + nsAutoCString host; 1.1830 + uint32_t hostHash = 0; 1.1831 + if (NS_SUCCEEDED(baseURI->GetAsciiHost(host))) 1.1832 + hostHash = mozilla::HashString(host); 1.1833 + 1.1834 + return mozilla::AddToHash(schemeHash, hostHash, NS_GetRealPort(baseURI)); 1.1835 +} 1.1836 + 1.1837 +inline bool 1.1838 +NS_SecurityCompareURIs(nsIURI* aSourceURI, 1.1839 + nsIURI* aTargetURI, 1.1840 + bool aStrictFileOriginPolicy) 1.1841 +{ 1.1842 + // Note that this is not an Equals() test on purpose -- for URIs that don't 1.1843 + // support host/port, we want equality to basically be object identity, for 1.1844 + // security purposes. Otherwise, for example, two javascript: URIs that 1.1845 + // are otherwise unrelated could end up "same origin", which would be 1.1846 + // unfortunate. 1.1847 + if (aSourceURI && aSourceURI == aTargetURI) 1.1848 + { 1.1849 + return true; 1.1850 + } 1.1851 + 1.1852 + if (!aTargetURI || !aSourceURI) 1.1853 + { 1.1854 + return false; 1.1855 + } 1.1856 + 1.1857 + // If either URI is a nested URI, get the base URI 1.1858 + nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(aSourceURI); 1.1859 + nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI); 1.1860 + 1.1861 + // If either uri is an nsIURIWithPrincipal 1.1862 + nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(sourceBaseURI); 1.1863 + if (uriPrinc) { 1.1864 + uriPrinc->GetPrincipalUri(getter_AddRefs(sourceBaseURI)); 1.1865 + } 1.1866 + 1.1867 + uriPrinc = do_QueryInterface(targetBaseURI); 1.1868 + if (uriPrinc) { 1.1869 + uriPrinc->GetPrincipalUri(getter_AddRefs(targetBaseURI)); 1.1870 + } 1.1871 + 1.1872 + if (!sourceBaseURI || !targetBaseURI) 1.1873 + return false; 1.1874 + 1.1875 + // Compare schemes 1.1876 + nsAutoCString targetScheme; 1.1877 + bool sameScheme = false; 1.1878 + if (NS_FAILED( targetBaseURI->GetScheme(targetScheme) ) || 1.1879 + NS_FAILED( sourceBaseURI->SchemeIs(targetScheme.get(), &sameScheme) ) || 1.1880 + !sameScheme) 1.1881 + { 1.1882 + // Not same-origin if schemes differ 1.1883 + return false; 1.1884 + } 1.1885 + 1.1886 + // For file scheme, reject unless the files are identical. See 1.1887 + // NS_RelaxStrictFileOriginPolicy for enforcing file same-origin checking 1.1888 + if (targetScheme.EqualsLiteral("file")) 1.1889 + { 1.1890 + // in traditional unsafe behavior all files are the same origin 1.1891 + if (!aStrictFileOriginPolicy) 1.1892 + return true; 1.1893 + 1.1894 + nsCOMPtr<nsIFileURL> sourceFileURL(do_QueryInterface(sourceBaseURI)); 1.1895 + nsCOMPtr<nsIFileURL> targetFileURL(do_QueryInterface(targetBaseURI)); 1.1896 + 1.1897 + if (!sourceFileURL || !targetFileURL) 1.1898 + return false; 1.1899 + 1.1900 + nsCOMPtr<nsIFile> sourceFile, targetFile; 1.1901 + 1.1902 + sourceFileURL->GetFile(getter_AddRefs(sourceFile)); 1.1903 + targetFileURL->GetFile(getter_AddRefs(targetFile)); 1.1904 + 1.1905 + if (!sourceFile || !targetFile) 1.1906 + return false; 1.1907 + 1.1908 + // Otherwise they had better match 1.1909 + bool filesAreEqual = false; 1.1910 + nsresult rv = sourceFile->Equals(targetFile, &filesAreEqual); 1.1911 + return NS_SUCCEEDED(rv) && filesAreEqual; 1.1912 + } 1.1913 + 1.1914 + // Special handling for mailnews schemes 1.1915 + if (targetScheme.EqualsLiteral("imap") || 1.1916 + targetScheme.EqualsLiteral("mailbox") || 1.1917 + targetScheme.EqualsLiteral("news")) 1.1918 + { 1.1919 + // Each message is a distinct trust domain; use the 1.1920 + // whole spec for comparison 1.1921 + nsAutoCString targetSpec; 1.1922 + nsAutoCString sourceSpec; 1.1923 + return ( NS_SUCCEEDED( targetBaseURI->GetSpec(targetSpec) ) && 1.1924 + NS_SUCCEEDED( sourceBaseURI->GetSpec(sourceSpec) ) && 1.1925 + targetSpec.Equals(sourceSpec) ); 1.1926 + } 1.1927 + 1.1928 + // Compare hosts 1.1929 + nsAutoCString targetHost; 1.1930 + nsAutoCString sourceHost; 1.1931 + if (NS_FAILED( targetBaseURI->GetAsciiHost(targetHost) ) || 1.1932 + NS_FAILED( sourceBaseURI->GetAsciiHost(sourceHost) )) 1.1933 + { 1.1934 + return false; 1.1935 + } 1.1936 + 1.1937 + nsCOMPtr<nsIStandardURL> targetURL(do_QueryInterface(targetBaseURI)); 1.1938 + nsCOMPtr<nsIStandardURL> sourceURL(do_QueryInterface(sourceBaseURI)); 1.1939 + if (!targetURL || !sourceURL) 1.1940 + { 1.1941 + return false; 1.1942 + } 1.1943 + 1.1944 +#ifdef MOZILLA_INTERNAL_API 1.1945 + if (!targetHost.Equals(sourceHost, nsCaseInsensitiveCStringComparator() )) 1.1946 +#else 1.1947 + if (!targetHost.Equals(sourceHost, CaseInsensitiveCompare)) 1.1948 +#endif 1.1949 + { 1.1950 + return false; 1.1951 + } 1.1952 + 1.1953 + return NS_GetRealPort(targetBaseURI) == NS_GetRealPort(sourceBaseURI); 1.1954 +} 1.1955 + 1.1956 +inline bool 1.1957 +NS_URIIsLocalFile(nsIURI *aURI) 1.1958 +{ 1.1959 + nsCOMPtr<nsINetUtil> util = do_GetNetUtil(); 1.1960 + 1.1961 + bool isFile; 1.1962 + return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI, 1.1963 + nsIProtocolHandler::URI_IS_LOCAL_FILE, 1.1964 + &isFile)) && 1.1965 + isFile; 1.1966 +} 1.1967 + 1.1968 +// When strict file origin policy is enabled, SecurityCompareURIs will fail for 1.1969 +// file URIs that do not point to the same local file. This call provides an 1.1970 +// alternate file-specific origin check that allows target files that are 1.1971 +// contained in the same directory as the source. 1.1972 +// 1.1973 +// https://developer.mozilla.org/en-US/docs/Same-origin_policy_for_file:_URIs 1.1974 +inline bool 1.1975 +NS_RelaxStrictFileOriginPolicy(nsIURI *aTargetURI, 1.1976 + nsIURI *aSourceURI, 1.1977 + bool aAllowDirectoryTarget = false) 1.1978 +{ 1.1979 + if (!NS_URIIsLocalFile(aTargetURI)) { 1.1980 + // This is probably not what the caller intended 1.1981 + NS_NOTREACHED("NS_RelaxStrictFileOriginPolicy called with non-file URI"); 1.1982 + return false; 1.1983 + } 1.1984 + 1.1985 + if (!NS_URIIsLocalFile(aSourceURI)) { 1.1986 + // If the source is not also a file: uri then forget it 1.1987 + // (don't want resource: principals in a file: doc) 1.1988 + // 1.1989 + // note: we're not de-nesting jar: uris here, we want to 1.1990 + // keep archive content bottled up in its own little island 1.1991 + return false; 1.1992 + } 1.1993 + 1.1994 + // 1.1995 + // pull out the internal files 1.1996 + // 1.1997 + nsCOMPtr<nsIFileURL> targetFileURL(do_QueryInterface(aTargetURI)); 1.1998 + nsCOMPtr<nsIFileURL> sourceFileURL(do_QueryInterface(aSourceURI)); 1.1999 + nsCOMPtr<nsIFile> targetFile; 1.2000 + nsCOMPtr<nsIFile> sourceFile; 1.2001 + bool targetIsDir; 1.2002 + 1.2003 + // Make sure targetFile is not a directory (bug 209234) 1.2004 + // and that it exists w/out unescaping (bug 395343) 1.2005 + if (!sourceFileURL || !targetFileURL || 1.2006 + NS_FAILED(targetFileURL->GetFile(getter_AddRefs(targetFile))) || 1.2007 + NS_FAILED(sourceFileURL->GetFile(getter_AddRefs(sourceFile))) || 1.2008 + !targetFile || !sourceFile || 1.2009 + NS_FAILED(targetFile->Normalize()) || 1.2010 +#ifndef MOZ_WIDGET_ANDROID 1.2011 + NS_FAILED(sourceFile->Normalize()) || 1.2012 +#endif 1.2013 + (!aAllowDirectoryTarget && 1.2014 + (NS_FAILED(targetFile->IsDirectory(&targetIsDir)) || targetIsDir))) { 1.2015 + return false; 1.2016 + } 1.2017 + 1.2018 + // 1.2019 + // If the file to be loaded is in a subdirectory of the source 1.2020 + // (or same-dir if source is not a directory) then it will 1.2021 + // inherit its source principal and be scriptable by that source. 1.2022 + // 1.2023 + bool sourceIsDir; 1.2024 + bool allowed = false; 1.2025 + nsresult rv = sourceFile->IsDirectory(&sourceIsDir); 1.2026 + if (NS_SUCCEEDED(rv) && sourceIsDir) { 1.2027 + rv = sourceFile->Contains(targetFile, true, &allowed); 1.2028 + } else { 1.2029 + nsCOMPtr<nsIFile> sourceParent; 1.2030 + rv = sourceFile->GetParent(getter_AddRefs(sourceParent)); 1.2031 + if (NS_SUCCEEDED(rv) && sourceParent) { 1.2032 + rv = sourceParent->Equals(targetFile, &allowed); 1.2033 + if (NS_FAILED(rv) || !allowed) { 1.2034 + rv = sourceParent->Contains(targetFile, true, &allowed); 1.2035 + } else { 1.2036 + MOZ_ASSERT(aAllowDirectoryTarget, 1.2037 + "sourceFile->Parent == targetFile, but targetFile " 1.2038 + "should've been disallowed if it is a directory"); 1.2039 + } 1.2040 + } 1.2041 + } 1.2042 + 1.2043 + if (NS_SUCCEEDED(rv) && allowed) { 1.2044 + return true; 1.2045 + } 1.2046 + 1.2047 + return false; 1.2048 +} 1.2049 + 1.2050 +inline bool 1.2051 +NS_IsInternalSameURIRedirect(nsIChannel *aOldChannel, 1.2052 + nsIChannel *aNewChannel, 1.2053 + uint32_t aFlags) 1.2054 +{ 1.2055 + if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) { 1.2056 + return false; 1.2057 + } 1.2058 + 1.2059 + nsCOMPtr<nsIURI> oldURI, newURI; 1.2060 + aOldChannel->GetURI(getter_AddRefs(oldURI)); 1.2061 + aNewChannel->GetURI(getter_AddRefs(newURI)); 1.2062 + 1.2063 + if (!oldURI || !newURI) { 1.2064 + return false; 1.2065 + } 1.2066 + 1.2067 + bool res; 1.2068 + return NS_SUCCEEDED(oldURI->Equals(newURI, &res)) && res; 1.2069 +} 1.2070 + 1.2071 +inline nsresult 1.2072 +NS_LinkRedirectChannels(uint32_t channelId, 1.2073 + nsIParentChannel *parentChannel, 1.2074 + nsIChannel** _result) 1.2075 +{ 1.2076 + nsresult rv; 1.2077 + 1.2078 + nsCOMPtr<nsIRedirectChannelRegistrar> registrar = 1.2079 + do_GetService("@mozilla.org/redirectchannelregistrar;1", &rv); 1.2080 + NS_ENSURE_SUCCESS(rv, rv); 1.2081 + 1.2082 + return registrar->LinkChannels(channelId, 1.2083 + parentChannel, 1.2084 + _result); 1.2085 +} 1.2086 + 1.2087 +/** 1.2088 + * Helper function to create a random URL string that's properly formed 1.2089 + * but guaranteed to be invalid. 1.2090 + */ 1.2091 +#define NS_FAKE_SCHEME "http://" 1.2092 +#define NS_FAKE_TLD ".invalid" 1.2093 +inline nsresult 1.2094 +NS_MakeRandomInvalidURLString(nsCString& result) 1.2095 +{ 1.2096 + nsresult rv; 1.2097 + nsCOMPtr<nsIUUIDGenerator> uuidgen = 1.2098 + do_GetService("@mozilla.org/uuid-generator;1", &rv); 1.2099 + NS_ENSURE_SUCCESS(rv, rv); 1.2100 + 1.2101 + nsID idee; 1.2102 + rv = uuidgen->GenerateUUIDInPlace(&idee); 1.2103 + NS_ENSURE_SUCCESS(rv, rv); 1.2104 + 1.2105 + char chars[NSID_LENGTH]; 1.2106 + idee.ToProvidedString(chars); 1.2107 + 1.2108 + result.AssignLiteral(NS_FAKE_SCHEME); 1.2109 + // Strip off the '{' and '}' at the beginning and end of the UUID 1.2110 + result.Append(chars + 1, NSID_LENGTH - 3); 1.2111 + result.AppendLiteral(NS_FAKE_TLD); 1.2112 + 1.2113 + return NS_OK; 1.2114 +} 1.2115 +#undef NS_FAKE_SCHEME 1.2116 +#undef NS_FAKE_TLD 1.2117 + 1.2118 +/** 1.2119 + * Helper function to determine whether urlString is Java-compatible -- 1.2120 + * whether it can be passed to the Java URL(String) constructor without the 1.2121 + * latter throwing a MalformedURLException, or without Java otherwise 1.2122 + * mishandling it. This function (in effect) implements a scheme whitelist 1.2123 + * for Java. 1.2124 + */ 1.2125 +inline nsresult 1.2126 +NS_CheckIsJavaCompatibleURLString(nsCString& urlString, bool *result) 1.2127 +{ 1.2128 + *result = false; // Default to "no" 1.2129 + 1.2130 + nsresult rv = NS_OK; 1.2131 + nsCOMPtr<nsIURLParser> urlParser = 1.2132 + do_GetService(NS_STDURLPARSER_CONTRACTID, &rv); 1.2133 + if (NS_FAILED(rv) || !urlParser) 1.2134 + return NS_ERROR_FAILURE; 1.2135 + 1.2136 + bool compatible = true; 1.2137 + uint32_t schemePos = 0; 1.2138 + int32_t schemeLen = 0; 1.2139 + urlParser->ParseURL(urlString.get(), -1, &schemePos, &schemeLen, 1.2140 + nullptr, nullptr, nullptr, nullptr); 1.2141 + if (schemeLen != -1) { 1.2142 + nsCString scheme; 1.2143 + scheme.Assign(urlString.get() + schemePos, schemeLen); 1.2144 + // By default Java only understands a small number of URL schemes, and of 1.2145 + // these only some can legitimately represent a browser page's "origin" 1.2146 + // (and be something we can legitimately expect Java to handle ... or not 1.2147 + // to mishandle). 1.2148 + // 1.2149 + // Besides those listed below, the OJI plugin understands the "jar", 1.2150 + // "mailto", "netdoc", "javascript" and "rmi" schemes, and Java Plugin2 1.2151 + // also understands the "about" scheme. We actually pass "about" URLs 1.2152 + // to Java ("about:blank" when processing a javascript: URL (one that 1.2153 + // calls Java) from the location bar of a blank page, and (in FF4 and up) 1.2154 + // "about:home" when processing a javascript: URL from the home page). 1.2155 + // And Java doesn't appear to mishandle them (for example it doesn't allow 1.2156 + // connections to "about" URLs). But it doesn't make any sense to do 1.2157 + // same-origin checks on "about" URLs, so we don't include them in our 1.2158 + // scheme whitelist. 1.2159 + // 1.2160 + // The OJI plugin doesn't understand "chrome" URLs (only Java Plugin2 1.2161 + // does) -- so we mustn't pass them to the OJI plugin. But we do need to 1.2162 + // pass "chrome" URLs to Java Plugin2: Java Plugin2 grants additional 1.2163 + // privileges to chrome "origins", and some extensions take advantage of 1.2164 + // this. For more information see bug 620773. 1.2165 + // 1.2166 + // As of FF4, we no longer support the OJI plugin. 1.2167 + if (PL_strcasecmp(scheme.get(), "http") && 1.2168 + PL_strcasecmp(scheme.get(), "https") && 1.2169 + PL_strcasecmp(scheme.get(), "file") && 1.2170 + PL_strcasecmp(scheme.get(), "ftp") && 1.2171 + PL_strcasecmp(scheme.get(), "gopher") && 1.2172 + PL_strcasecmp(scheme.get(), "chrome")) 1.2173 + compatible = false; 1.2174 + } else { 1.2175 + compatible = false; 1.2176 + } 1.2177 + 1.2178 + *result = compatible; 1.2179 + 1.2180 + return NS_OK; 1.2181 +} 1.2182 + 1.2183 +/** Given the first (disposition) token from a Content-Disposition header, 1.2184 + * tell whether it indicates the content is inline or attachment 1.2185 + * @param aDispToken the disposition token from the content-disposition header 1.2186 + */ 1.2187 +inline uint32_t 1.2188 +NS_GetContentDispositionFromToken(const nsAString& aDispToken) 1.2189 +{ 1.2190 + // RFC 2183, section 2.8 says that an unknown disposition 1.2191 + // value should be treated as "attachment" 1.2192 + // If all of these tests eval to false, then we have a content-disposition of 1.2193 + // "attachment" or unknown 1.2194 + if (aDispToken.IsEmpty() || 1.2195 + aDispToken.LowerCaseEqualsLiteral("inline") || 1.2196 + // Broken sites just send 1.2197 + // Content-Disposition: filename="file" 1.2198 + // without a disposition token... screen those out. 1.2199 + StringHead(aDispToken, 8).LowerCaseEqualsLiteral("filename")) 1.2200 + return nsIChannel::DISPOSITION_INLINE; 1.2201 + 1.2202 + return nsIChannel::DISPOSITION_ATTACHMENT; 1.2203 +} 1.2204 + 1.2205 +/** Determine the disposition (inline/attachment) of the content based on the 1.2206 + * Content-Disposition header 1.2207 + * @param aHeader the content-disposition header (full value) 1.2208 + * @param aChan the channel the header came from 1.2209 + */ 1.2210 +inline uint32_t 1.2211 +NS_GetContentDispositionFromHeader(const nsACString& aHeader, nsIChannel *aChan = nullptr) 1.2212 +{ 1.2213 + nsresult rv; 1.2214 + nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar = do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv); 1.2215 + if (NS_FAILED(rv)) 1.2216 + return nsIChannel::DISPOSITION_ATTACHMENT; 1.2217 + 1.2218 + nsAutoCString fallbackCharset; 1.2219 + if (aChan) { 1.2220 + nsCOMPtr<nsIURI> uri; 1.2221 + aChan->GetURI(getter_AddRefs(uri)); 1.2222 + if (uri) 1.2223 + uri->GetOriginCharset(fallbackCharset); 1.2224 + } 1.2225 + 1.2226 + nsAutoString dispToken; 1.2227 + rv = mimehdrpar->GetParameterHTTP(aHeader, "", fallbackCharset, true, nullptr, 1.2228 + dispToken); 1.2229 + 1.2230 + if (NS_FAILED(rv)) { 1.2231 + // special case (see bug 272541): empty disposition type handled as "inline" 1.2232 + if (rv == NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY) 1.2233 + return nsIChannel::DISPOSITION_INLINE; 1.2234 + return nsIChannel::DISPOSITION_ATTACHMENT; 1.2235 + } 1.2236 + 1.2237 + return NS_GetContentDispositionFromToken(dispToken); 1.2238 +} 1.2239 + 1.2240 +/** Extracts the filename out of a content-disposition header 1.2241 + * @param aFilename [out] The filename. Can be empty on error. 1.2242 + * @param aDisposition Value of a Content-Disposition header 1.2243 + * @param aURI Optional. Will be used to get a fallback charset for the 1.2244 + * filename, if it is QI'able to nsIURL 1.2245 + */ 1.2246 +inline nsresult 1.2247 +NS_GetFilenameFromDisposition(nsAString& aFilename, 1.2248 + const nsACString& aDisposition, 1.2249 + nsIURI* aURI = nullptr) 1.2250 +{ 1.2251 + aFilename.Truncate(); 1.2252 + 1.2253 + nsresult rv; 1.2254 + nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar = 1.2255 + do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv); 1.2256 + if (NS_FAILED(rv)) 1.2257 + return rv; 1.2258 + 1.2259 + nsCOMPtr<nsIURL> url = do_QueryInterface(aURI); 1.2260 + 1.2261 + nsAutoCString fallbackCharset; 1.2262 + if (url) 1.2263 + url->GetOriginCharset(fallbackCharset); 1.2264 + // Get the value of 'filename' parameter 1.2265 + rv = mimehdrpar->GetParameterHTTP(aDisposition, "filename", 1.2266 + fallbackCharset, true, nullptr, 1.2267 + aFilename); 1.2268 + 1.2269 + if (NS_FAILED(rv)) { 1.2270 + aFilename.Truncate(); 1.2271 + return rv; 1.2272 + } 1.2273 + 1.2274 + if (aFilename.IsEmpty()) 1.2275 + return NS_ERROR_NOT_AVAILABLE; 1.2276 + 1.2277 + return NS_OK; 1.2278 +} 1.2279 + 1.2280 +/** 1.2281 + * Make sure Personal Security Manager is initialized 1.2282 + */ 1.2283 +inline void 1.2284 +net_EnsurePSMInit() 1.2285 +{ 1.2286 + nsCOMPtr<nsISocketProviderService> spserv = 1.2287 + do_GetService(NS_SOCKETPROVIDERSERVICE_CONTRACTID); 1.2288 + if (spserv) { 1.2289 + nsCOMPtr<nsISocketProvider> provider; 1.2290 + spserv->GetSocketProvider("ssl", getter_AddRefs(provider)); 1.2291 + } 1.2292 +} 1.2293 + 1.2294 +/** 1.2295 + * Test whether a URI is "about:blank". |uri| must not be null 1.2296 + */ 1.2297 +inline bool 1.2298 +NS_IsAboutBlank(nsIURI *uri) 1.2299 +{ 1.2300 + // GetSpec can be expensive for some URIs, so check the scheme first. 1.2301 + bool isAbout = false; 1.2302 + if (NS_FAILED(uri->SchemeIs("about", &isAbout)) || !isAbout) { 1.2303 + return false; 1.2304 + } 1.2305 + 1.2306 + nsAutoCString str; 1.2307 + uri->GetSpec(str); 1.2308 + return str.EqualsLiteral("about:blank"); 1.2309 +} 1.2310 + 1.2311 + 1.2312 +inline nsresult 1.2313 +NS_GenerateHostPort(const nsCString& host, int32_t port, 1.2314 + nsCString& hostLine) 1.2315 +{ 1.2316 + if (strchr(host.get(), ':')) { 1.2317 + // host is an IPv6 address literal and must be encapsulated in []'s 1.2318 + hostLine.Assign('['); 1.2319 + // scope id is not needed for Host header. 1.2320 + int scopeIdPos = host.FindChar('%'); 1.2321 + if (scopeIdPos == -1) 1.2322 + hostLine.Append(host); 1.2323 + else if (scopeIdPos > 0) 1.2324 + hostLine.Append(Substring(host, 0, scopeIdPos)); 1.2325 + else 1.2326 + return NS_ERROR_MALFORMED_URI; 1.2327 + hostLine.Append(']'); 1.2328 + } 1.2329 + else 1.2330 + hostLine.Assign(host); 1.2331 + if (port != -1) { 1.2332 + hostLine.Append(':'); 1.2333 + hostLine.AppendInt(port); 1.2334 + } 1.2335 + return NS_OK; 1.2336 +} 1.2337 + 1.2338 +/** 1.2339 + * Sniff the content type for a given request or a given buffer. 1.2340 + * 1.2341 + * aSnifferType can be either NS_CONTENT_SNIFFER_CATEGORY or 1.2342 + * NS_DATA_SNIFFER_CATEGORY. The function returns the sniffed content type 1.2343 + * in the aSniffedType argument. This argument will not be modified if the 1.2344 + * content type could not be sniffed. 1.2345 + */ 1.2346 +inline void 1.2347 +NS_SniffContent(const char* aSnifferType, nsIRequest* aRequest, 1.2348 + const uint8_t* aData, uint32_t aLength, 1.2349 + nsACString& aSniffedType) 1.2350 +{ 1.2351 + typedef nsCategoryCache<nsIContentSniffer> ContentSnifferCache; 1.2352 + extern NS_HIDDEN_(ContentSnifferCache*) gNetSniffers; 1.2353 + extern NS_HIDDEN_(ContentSnifferCache*) gDataSniffers; 1.2354 + ContentSnifferCache* cache = nullptr; 1.2355 + if (!strcmp(aSnifferType, NS_CONTENT_SNIFFER_CATEGORY)) { 1.2356 + if (!gNetSniffers) { 1.2357 + gNetSniffers = new ContentSnifferCache(NS_CONTENT_SNIFFER_CATEGORY); 1.2358 + } 1.2359 + cache = gNetSniffers; 1.2360 + } else if (!strcmp(aSnifferType, NS_DATA_SNIFFER_CATEGORY)) { 1.2361 + if (!gDataSniffers) { 1.2362 + gDataSniffers = new ContentSnifferCache(NS_DATA_SNIFFER_CATEGORY); 1.2363 + } 1.2364 + cache = gDataSniffers; 1.2365 + } else { 1.2366 + // Invalid content sniffer type was requested 1.2367 + MOZ_ASSERT(false); 1.2368 + return; 1.2369 + } 1.2370 + 1.2371 + nsCOMArray<nsIContentSniffer> sniffers; 1.2372 + cache->GetEntries(sniffers); 1.2373 + for (int32_t i = 0; i < sniffers.Count(); ++i) { 1.2374 + nsresult rv = sniffers[i]->GetMIMETypeFromContent(aRequest, aData, aLength, aSniffedType); 1.2375 + if (NS_SUCCEEDED(rv) && !aSniffedType.IsEmpty()) { 1.2376 + return; 1.2377 + } 1.2378 + } 1.2379 + 1.2380 + aSniffedType.Truncate(); 1.2381 +} 1.2382 + 1.2383 +/** 1.2384 + * Whether the channel was created to load a srcdoc document. 1.2385 + * Note that view-source:about:srcdoc is classified as a srcdoc document by 1.2386 + * this function, which may not be applicable everywhere. 1.2387 + */ 1.2388 +inline bool 1.2389 +NS_IsSrcdocChannel(nsIChannel *aChannel) 1.2390 +{ 1.2391 + bool isSrcdoc; 1.2392 + nsCOMPtr<nsIInputStreamChannel> isr = do_QueryInterface(aChannel); 1.2393 + if (isr) { 1.2394 + isr->GetIsSrcdocChannel(&isSrcdoc); 1.2395 + return isSrcdoc; 1.2396 + } 1.2397 + nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(aChannel); 1.2398 + if (vsc) { 1.2399 + vsc->GetIsSrcdocChannel(&isSrcdoc); 1.2400 + return isSrcdoc; 1.2401 + } 1.2402 + return false; 1.2403 +} 1.2404 + 1.2405 +#endif // !nsNetUtil_h__