2018-11-30 22:52:05 +03:00
|
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2018-11-30 18:39:55 +03:00
|
|
|
|
/* vim:set ts=4 sw=2 sts=2 et cin: */
|
2014-07-24 20:38:55 +04:00
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
2015-11-02 19:27:00 +03:00
|
|
|
|
// HttpLog.h should generally be included first
|
|
|
|
|
#include "HttpLog.h"
|
|
|
|
|
|
2017-06-18 14:37:50 +03:00
|
|
|
|
#include "nsNetUtil.h"
|
|
|
|
|
|
2018-02-28 09:14:41 +03:00
|
|
|
|
#include "mozilla/Atomics.h"
|
Bug 1689191 - restrict nsISiteSecurityService and DataStorage to the main process r=rmf,necko-reviewers,ipc-reviewers,kershaw,nika
Bug 1215723 introduced a mechanism whereby DataStorage data would be propagated
to content processes to avoid the IPC calls involved in querying if hosts were
HSTS. With a low number of content processes, this was a reasonable approach.
However, with Fission and the proliferation of content processes, propagating
changes in DataStorage data to every content process wakes up unrelated
processes and is inefficient. This patch restores the behavior that
nsISiteSecurityService and DataStorage is not available to content processes.
Additionally, bug 1626076 made it possible to use DataStorage directly from the
socket process. However, as of bug 1650356, this is no longer necessary, so
this patch removes that behavior as well.
Differential Revision: https://phabricator.services.mozilla.com/D118207
2021-06-25 02:39:52 +03:00
|
|
|
|
#include "mozilla/BasePrincipal.h"
|
2021-02-18 16:26:32 +03:00
|
|
|
|
#include "mozilla/Components.h"
|
2017-06-18 14:37:50 +03:00
|
|
|
|
#include "mozilla/Encoding.h"
|
2014-12-15 16:39:00 +03:00
|
|
|
|
#include "mozilla/LoadContext.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
#include "mozilla/LoadInfo.h"
|
2017-11-09 13:18:08 +03:00
|
|
|
|
#include "mozilla/Monitor.h"
|
2019-12-11 23:17:53 +03:00
|
|
|
|
#include "mozilla/StaticPrefs_network.h"
|
2019-07-26 04:10:23 +03:00
|
|
|
|
#include "mozilla/StaticPrefs_privacy.h"
|
2019-04-12 08:30:43 +03:00
|
|
|
|
#include "mozilla/StoragePrincipalHelper.h"
|
2017-11-09 13:18:08 +03:00
|
|
|
|
#include "mozilla/TaskQueue.h"
|
2016-01-09 04:20:50 +03:00
|
|
|
|
#include "mozilla/Telemetry.h"
|
2019-12-03 16:45:19 +03:00
|
|
|
|
#include "nsBufferedStreams.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
#include "nsCategoryCache.h"
|
2020-11-23 19:21:38 +03:00
|
|
|
|
#include "nsComponentManagerUtils.h"
|
2015-11-09 05:54:38 +03:00
|
|
|
|
#include "nsContentUtils.h"
|
2018-09-10 02:18:19 +03:00
|
|
|
|
#include "nsFileStreams.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
#include "nsHashKeys.h"
|
2014-07-24 20:38:55 +04:00
|
|
|
|
#include "nsHttp.h"
|
2019-09-24 15:26:22 +03:00
|
|
|
|
#include "nsMimeTypes.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
#include "nsIAuthPrompt.h"
|
|
|
|
|
#include "nsIAuthPrompt2.h"
|
|
|
|
|
#include "nsIAuthPromptAdapterFactory.h"
|
|
|
|
|
#include "nsIBufferedStreams.h"
|
2019-08-15 20:25:51 +03:00
|
|
|
|
#include "nsBufferedStreams.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
#include "nsIChannelEventSink.h"
|
|
|
|
|
#include "nsIContentSniffer.h"
|
2019-01-02 16:05:23 +03:00
|
|
|
|
#include "mozilla/dom/Document.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
#include "nsIDownloader.h"
|
|
|
|
|
#include "nsIFileProtocolHandler.h"
|
|
|
|
|
#include "nsIFileStreams.h"
|
|
|
|
|
#include "nsIFileURL.h"
|
|
|
|
|
#include "nsIIDNService.h"
|
|
|
|
|
#include "nsIInputStreamChannel.h"
|
|
|
|
|
#include "nsIInputStreamPump.h"
|
|
|
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
|
|
|
#include "nsILoadContext.h"
|
|
|
|
|
#include "nsIMIMEHeaderParam.h"
|
2016-07-28 09:44:22 +03:00
|
|
|
|
#include "nsINode.h"
|
2017-04-20 05:15:06 +03:00
|
|
|
|
#include "nsIObjectLoadingContent.h"
|
2018-09-15 19:58:31 +03:00
|
|
|
|
#include "nsPersistentProperties.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
#include "nsIPrivateBrowsingChannel.h"
|
|
|
|
|
#include "nsIPropertyBag2.h"
|
|
|
|
|
#include "nsIProtocolProxyService.h"
|
2018-08-22 07:37:28 +03:00
|
|
|
|
#include "mozilla/net/RedirectChannelRegistrar.h"
|
2018-10-23 23:07:19 +03:00
|
|
|
|
#include "nsRequestObserverProxy.h"
|
2017-08-07 16:56:30 +03:00
|
|
|
|
#include "nsISensitiveInfoHiddenURI.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
#include "nsISimpleStreamListener.h"
|
|
|
|
|
#include "nsISocketProvider.h"
|
|
|
|
|
#include "nsIStandardURL.h"
|
|
|
|
|
#include "nsIStreamLoader.h"
|
2015-11-30 17:54:11 +03:00
|
|
|
|
#include "nsIIncrementalStreamLoader.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
#include "nsStringStream.h"
|
2018-10-23 23:07:29 +03:00
|
|
|
|
#include "nsSyncStreamListener.h"
|
2020-02-06 21:23:45 +03:00
|
|
|
|
#include "nsITextToSubURI.h"
|
2018-07-31 11:27:00 +03:00
|
|
|
|
#include "nsIURIWithSpecialOrigin.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
#include "nsIViewSourceChannel.h"
|
|
|
|
|
#include "nsInterfaceRequestorAgg.h"
|
|
|
|
|
#include "plstr.h"
|
|
|
|
|
#include "nsINestedURI.h"
|
2015-11-02 19:27:00 +03:00
|
|
|
|
#include "mozilla/dom/nsCSPUtils.h"
|
2020-03-17 22:24:31 +03:00
|
|
|
|
#include "mozilla/dom/nsHTTPSOnlyUtils.h"
|
2018-10-31 19:04:58 +03:00
|
|
|
|
#include "mozilla/dom/nsMixedContentBlocker.h"
|
2018-07-24 23:15:57 +03:00
|
|
|
|
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
2016-02-18 06:03:41 +03:00
|
|
|
|
#include "mozilla/net/HttpBaseChannel.h"
|
2015-11-02 19:27:00 +03:00
|
|
|
|
#include "nsIScriptError.h"
|
|
|
|
|
#include "nsISiteSecurityService.h"
|
|
|
|
|
#include "nsHttpHandler.h"
|
2016-10-25 17:43:00 +03:00
|
|
|
|
#include "nsNSSComponent.h"
|
2017-05-25 20:42:00 +03:00
|
|
|
|
#include "nsIRedirectHistoryEntry.h"
|
2021-01-20 01:11:25 +03:00
|
|
|
|
#include "nsICertStorage.h"
|
2017-12-20 05:08:15 +03:00
|
|
|
|
#include "nsICertOverrideService.h"
|
2018-02-09 23:17:26 +03:00
|
|
|
|
#include "nsQueryObject.h"
|
|
|
|
|
#include "mozIThirdPartyUtil.h"
|
2018-08-06 22:31:22 +03:00
|
|
|
|
#include "../mime/nsMIMEHeaderParamImpl.h"
|
2019-03-19 18:11:31 +03:00
|
|
|
|
#include "nsStandardURL.h"
|
2019-12-11 23:17:53 +03:00
|
|
|
|
#include "DefaultURI.h"
|
2019-03-19 18:11:31 +03:00
|
|
|
|
#include "nsChromeProtocolHandler.h"
|
|
|
|
|
#include "nsJSProtocolHandler.h"
|
|
|
|
|
#include "nsDataHandler.h"
|
2019-03-19 18:13:47 +03:00
|
|
|
|
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
2019-05-10 01:04:43 +03:00
|
|
|
|
#include "nsStreamUtils.h"
|
|
|
|
|
#include "nsSocketTransportService2.h"
|
2019-05-28 16:48:49 +03:00
|
|
|
|
#include "nsViewSourceHandler.h"
|
2019-05-28 16:49:07 +03:00
|
|
|
|
#include "nsJARURI.h"
|
2019-05-28 16:49:19 +03:00
|
|
|
|
#include "nsIconURI.h"
|
2019-05-28 16:49:17 +03:00
|
|
|
|
#include "nsAboutProtocolHandler.h"
|
2019-05-28 16:49:05 +03:00
|
|
|
|
#include "nsResProtocolHandler.h"
|
|
|
|
|
#include "mozilla/net/ExtensionProtocolHandler.h"
|
2020-04-06 20:46:52 +03:00
|
|
|
|
#include "mozilla/net/PageThumbProtocolHandler.h"
|
2020-09-01 09:18:51 +03:00
|
|
|
|
#include "mozilla/net/SFVService.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
#include <limits>
|
2021-08-03 19:46:34 +03:00
|
|
|
|
#include "nsIXPConnect.h"
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
2019-05-29 12:23:04 +03:00
|
|
|
|
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
|
|
|
|
|
# include "nsNewMailnewsURI.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-01-09 04:20:50 +03:00
|
|
|
|
using namespace mozilla;
|
|
|
|
|
using namespace mozilla::net;
|
2018-07-24 23:15:57 +03:00
|
|
|
|
using mozilla::dom::BlobURLProtocolHandler;
|
2018-01-23 18:38:54 +03:00
|
|
|
|
using mozilla::dom::ClientInfo;
|
2018-01-24 19:17:31 +03:00
|
|
|
|
using mozilla::dom::PerformanceStorage;
|
2018-01-23 18:38:54 +03:00
|
|
|
|
using mozilla::dom::ServiceWorkerDescriptor;
|
2016-01-09 04:20:50 +03:00
|
|
|
|
|
2019-05-10 01:04:43 +03:00
|
|
|
|
#define MAX_RECURSION_COUNT 50
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
already_AddRefed<nsIIOService> do_GetIOService(nsresult* error /* = 0 */) {
|
2021-02-18 16:26:32 +03:00
|
|
|
|
nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service();
|
2017-03-02 17:32:37 +03:00
|
|
|
|
if (error) *error = io ? NS_OK : NS_ERROR_FAILURE;
|
|
|
|
|
return io.forget();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewLocalFileInputStream(nsIInputStream** result, nsIFile* file,
|
|
|
|
|
int32_t ioFlags /* = -1 */,
|
|
|
|
|
int32_t perm /* = -1 */,
|
|
|
|
|
int32_t behaviorFlags /* = 0 */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIFileInputStream> in =
|
|
|
|
|
do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
rv = in->Init(file, ioFlags, perm, behaviorFlags);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) in.forget(result);
|
|
|
|
|
}
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-17 22:30:05 +03:00
|
|
|
|
Result<nsCOMPtr<nsIInputStream>, nsresult> NS_NewLocalFileInputStream(
|
|
|
|
|
nsIFile* file, int32_t ioFlags /* = -1 */, int32_t perm /* = -1 */,
|
|
|
|
|
int32_t behaviorFlags /* = 0 */) {
|
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
|
|
|
|
const nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file,
|
|
|
|
|
ioFlags, perm, behaviorFlags);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
return stream;
|
|
|
|
|
}
|
|
|
|
|
return Err(rv);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsresult NS_NewLocalFileOutputStream(nsIOutputStream** result, nsIFile* file,
|
|
|
|
|
int32_t ioFlags /* = -1 */,
|
|
|
|
|
int32_t perm /* = -1 */,
|
|
|
|
|
int32_t behaviorFlags /* = 0 */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIFileOutputStream> out =
|
|
|
|
|
do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
rv = out->Init(file, ioFlags, perm, behaviorFlags);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) out.forget(result);
|
|
|
|
|
}
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-17 22:30:05 +03:00
|
|
|
|
Result<nsCOMPtr<nsIOutputStream>, nsresult> NS_NewLocalFileOutputStream(
|
|
|
|
|
nsIFile* file, int32_t ioFlags /* = -1 */, int32_t perm /* = -1 */,
|
|
|
|
|
int32_t behaviorFlags /* = 0 */) {
|
|
|
|
|
nsCOMPtr<nsIOutputStream> stream;
|
|
|
|
|
const nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), file,
|
|
|
|
|
ioFlags, perm, behaviorFlags);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
return stream;
|
|
|
|
|
}
|
|
|
|
|
return Err(rv);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-20 12:41:58 +03:00
|
|
|
|
nsresult NS_NewLocalFileOutputStream(nsIOutputStream** result,
|
|
|
|
|
const mozilla::ipc::FileDescriptor& fd) {
|
|
|
|
|
nsCOMPtr<nsIFileOutputStream> out;
|
|
|
|
|
nsFileOutputStream::Create(nullptr, NS_GET_IID(nsIFileOutputStream),
|
|
|
|
|
getter_AddRefs(out));
|
|
|
|
|
|
|
|
|
|
nsresult rv =
|
|
|
|
|
static_cast<nsFileOutputStream*>(out.get())->InitWithFileDescriptor(fd);
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out.forget(result);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsresult net_EnsureIOService(nsIIOService** ios, nsCOMPtr<nsIIOService>& grip) {
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
if (!*ios) {
|
|
|
|
|
grip = do_GetIOService(&rv);
|
|
|
|
|
*ios = grip;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-03-02 17:32:37 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 14:28:47 +03:00
|
|
|
|
nsresult NS_NewFileURI(
|
|
|
|
|
nsIURI** result, nsIFile* spec,
|
|
|
|
|
nsIIOService*
|
|
|
|
|
ioService /* = nullptr */) // pass in nsIIOService to optimize callers
|
|
|
|
|
{
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIIOService> grip;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
rv = net_EnsureIOService(&ioService, grip);
|
2017-03-02 17:32:37 +03:00
|
|
|
|
if (ioService) rv = ioService->NewFileURI(spec, result);
|
|
|
|
|
return rv;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 14:28:47 +03:00
|
|
|
|
nsresult NS_GetURIWithNewRef(nsIURI* aInput, const nsACString& aRef,
|
|
|
|
|
nsIURI** aOutput) {
|
2020-06-22 15:51:58 +03:00
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(aRef.IsEmpty() || aRef[0] == '#');
|
|
|
|
|
|
2018-07-23 14:28:47 +03:00
|
|
|
|
if (NS_WARN_IF(!aInput || !aOutput)) {
|
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool hasRef;
|
|
|
|
|
nsresult rv = aInput->GetHasRef(&hasRef);
|
|
|
|
|
|
|
|
|
|
nsAutoCString ref;
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
rv = aInput->GetRef(ref);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the ref is already equal to the new ref, we do not need to do anything.
|
|
|
|
|
// Also, if the GetRef failed (it could return NS_ERROR_NOT_IMPLEMENTED)
|
|
|
|
|
// we can assume SetRef would fail as well, so returning the original
|
|
|
|
|
// URI is OK.
|
2020-06-22 15:51:58 +03:00
|
|
|
|
//
|
|
|
|
|
// Note that aRef contains the hash, but ref doesn't, so need to account for
|
|
|
|
|
// that in the equality check.
|
2018-07-23 14:28:47 +03:00
|
|
|
|
if (NS_FAILED(rv) || (!hasRef && aRef.IsEmpty()) ||
|
2020-06-22 15:51:58 +03:00
|
|
|
|
(!aRef.IsEmpty() && hasRef &&
|
|
|
|
|
Substring(aRef.Data() + 1, aRef.Length() - 1) == ref)) {
|
2018-07-23 14:28:47 +03:00
|
|
|
|
nsCOMPtr<nsIURI> uri = aInput;
|
|
|
|
|
uri.forget(aOutput);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_MutateURI(aInput).SetRef(aRef).Finalize(aOutput);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_GetURIWithoutRef(nsIURI* aInput, nsIURI** aOutput) {
|
2020-09-23 18:17:15 +03:00
|
|
|
|
return NS_GetURIWithNewRef(aInput, ""_ns, aOutput);
|
2018-07-23 14:28:47 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsresult NS_NewChannelInternal(
|
|
|
|
|
nsIChannel** outChannel, nsIURI* aUri, nsILoadInfo* aLoadInfo,
|
2018-01-24 19:17:31 +03:00
|
|
|
|
PerformanceStorage* aPerformanceStorage /* = nullptr */,
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsILoadGroup* aLoadGroup /* = nullptr */,
|
|
|
|
|
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
|
|
|
|
|
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
|
|
|
|
|
nsIIOService* aIoService /* = nullptr */) {
|
|
|
|
|
// NS_NewChannelInternal is mostly called for channel redirects. We should
|
|
|
|
|
// allow the creation of a channel even if the original channel did not have a
|
|
|
|
|
// loadinfo attached.
|
|
|
|
|
NS_ENSURE_ARG_POINTER(outChannel);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIIOService> grip;
|
|
|
|
|
nsresult rv = net_EnsureIOService(&aIoService, grip);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIChannel> channel;
|
|
|
|
|
rv = aIoService->NewChannelFromURIWithLoadInfo(aUri, aLoadInfo,
|
|
|
|
|
getter_AddRefs(channel));
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
if (aLoadGroup) {
|
|
|
|
|
rv = channel->SetLoadGroup(aLoadGroup);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aCallbacks) {
|
|
|
|
|
rv = channel->SetNotificationCallbacks(aCallbacks);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-30 19:07:59 +03:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
nsLoadFlags channelLoadFlags = 0;
|
|
|
|
|
channel->GetLoadFlags(&channelLoadFlags);
|
|
|
|
|
// Will be removed when we remove LOAD_REPLACE altogether
|
|
|
|
|
// This check is trying to catch protocol handlers that still
|
|
|
|
|
// try to set the LOAD_REPLACE flag.
|
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!(channelLoadFlags & nsIChannel::LOAD_REPLACE));
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
|
2017-05-30 19:07:59 +03:00
|
|
|
|
rv = channel->SetLoadFlags(aLoadFlags);
|
2017-03-02 17:32:37 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-24 19:17:31 +03:00
|
|
|
|
if (aPerformanceStorage) {
|
2019-02-20 15:27:25 +03:00
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
2018-01-24 19:17:31 +03:00
|
|
|
|
loadInfo->SetPerformanceStorage(aPerformanceStorage);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
channel.forget(outChannel);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-23 18:38:54 +03:00
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
void AssertLoadingPrincipalAndClientInfoMatch(
|
|
|
|
|
nsIPrincipal* aLoadingPrincipal, const ClientInfo& aLoadingClientInfo,
|
|
|
|
|
nsContentPolicyType aType) {
|
|
|
|
|
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
|
|
|
|
// Verify that the provided loading ClientInfo matches the loading
|
|
|
|
|
// principal. Unfortunately we can't just use nsIPrincipal::Equals() here
|
|
|
|
|
// because of some corner cases:
|
|
|
|
|
//
|
|
|
|
|
// 1. Worker debugger scripts want to use a system loading principal for
|
|
|
|
|
// worker scripts with a content principal. We exempt these from this
|
|
|
|
|
// check.
|
|
|
|
|
// 2. Null principals currently require exact object identity for
|
|
|
|
|
// nsIPrincipal::Equals() to return true. This doesn't work here because
|
|
|
|
|
// ClientInfo::GetPrincipal() uses PrincipalInfoToPrincipal() to allocate
|
|
|
|
|
// a new object. To work around this we compare the principal origin
|
|
|
|
|
// string itself. If bug 1431771 is fixed then we could switch to
|
|
|
|
|
// Equals().
|
|
|
|
|
|
|
|
|
|
// Allow worker debugger to load with a system principal.
|
2019-01-03 23:55:38 +03:00
|
|
|
|
if (aLoadingPrincipal->IsSystemPrincipal() &&
|
2018-01-23 18:38:54 +03:00
|
|
|
|
(aType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
|
|
|
|
|
aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER ||
|
|
|
|
|
aType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER ||
|
|
|
|
|
aType == nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Perform a fast comparison for most principal checks.
|
2020-05-12 22:02:05 +03:00
|
|
|
|
auto clientPrincipalOrErr(aLoadingClientInfo.GetPrincipal());
|
|
|
|
|
if (clientPrincipalOrErr.isOk()) {
|
|
|
|
|
nsCOMPtr<nsIPrincipal> clientPrincipal = clientPrincipalOrErr.unwrap();
|
|
|
|
|
if (aLoadingPrincipal->Equals(clientPrincipal)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Fall back to a slower origin equality test to support null principals.
|
2021-10-19 22:23:12 +03:00
|
|
|
|
nsAutoCString loadingOrigin;
|
|
|
|
|
MOZ_ALWAYS_SUCCEEDS(aLoadingPrincipal->GetOrigin(loadingOrigin));
|
|
|
|
|
|
|
|
|
|
nsAutoCString clientOrigin;
|
|
|
|
|
MOZ_ALWAYS_SUCCEEDS(clientPrincipal->GetOrigin(clientOrigin));
|
|
|
|
|
|
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(loadingOrigin == clientOrigin);
|
2018-01-23 18:38:54 +03:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewChannel(nsIChannel** outChannel, nsIURI* aUri,
|
|
|
|
|
nsIPrincipal* aLoadingPrincipal,
|
|
|
|
|
nsSecurityFlags aSecurityFlags,
|
|
|
|
|
nsContentPolicyType aContentPolicyType,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
nsICookieJarSettings* aCookieJarSettings /* = nullptr */,
|
2019-03-08 12:04:11 +03:00
|
|
|
|
PerformanceStorage* aPerformanceStorage /* = nullptr */,
|
2018-01-23 18:38:54 +03:00
|
|
|
|
nsILoadGroup* aLoadGroup /* = nullptr */,
|
|
|
|
|
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
|
|
|
|
|
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
|
2020-01-15 11:02:57 +03:00
|
|
|
|
nsIIOService* aIoService /* = nullptr */,
|
|
|
|
|
uint32_t aSandboxFlags /* = 0 */) {
|
2019-03-08 12:04:11 +03:00
|
|
|
|
return NS_NewChannelInternal(
|
|
|
|
|
outChannel, aUri,
|
|
|
|
|
nullptr, // aLoadingNode,
|
|
|
|
|
aLoadingPrincipal,
|
|
|
|
|
nullptr, // aTriggeringPrincipal
|
|
|
|
|
Maybe<ClientInfo>(), Maybe<ServiceWorkerDescriptor>(), aSecurityFlags,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
aContentPolicyType, aCookieJarSettings, aPerformanceStorage, aLoadGroup,
|
2020-01-15 11:02:57 +03:00
|
|
|
|
aCallbacks, aLoadFlags, aIoService, aSandboxFlags);
|
2018-01-23 18:38:54 +03:00
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsresult NS_NewChannel(nsIChannel** outChannel, nsIURI* aUri,
|
|
|
|
|
nsIPrincipal* aLoadingPrincipal,
|
2018-01-23 18:38:54 +03:00
|
|
|
|
const ClientInfo& aLoadingClientInfo,
|
|
|
|
|
const Maybe<ServiceWorkerDescriptor>& aController,
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsSecurityFlags aSecurityFlags,
|
|
|
|
|
nsContentPolicyType aContentPolicyType,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
nsICookieJarSettings* aCookieJarSettings /* = nullptr */,
|
2019-03-08 12:04:11 +03:00
|
|
|
|
PerformanceStorage* aPerformanceStorage /* = nullptr */,
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsILoadGroup* aLoadGroup /* = nullptr */,
|
|
|
|
|
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
|
|
|
|
|
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
|
2020-01-15 11:02:57 +03:00
|
|
|
|
nsIIOService* aIoService /* = nullptr */,
|
|
|
|
|
uint32_t aSandboxFlags /* = 0 */) {
|
2018-01-23 18:38:54 +03:00
|
|
|
|
AssertLoadingPrincipalAndClientInfoMatch(
|
|
|
|
|
aLoadingPrincipal, aLoadingClientInfo, aContentPolicyType);
|
|
|
|
|
|
|
|
|
|
Maybe<ClientInfo> loadingClientInfo;
|
|
|
|
|
loadingClientInfo.emplace(aLoadingClientInfo);
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
return NS_NewChannelInternal(outChannel, aUri,
|
|
|
|
|
nullptr, // aLoadingNode,
|
|
|
|
|
aLoadingPrincipal,
|
|
|
|
|
nullptr, // aTriggeringPrincipal
|
2018-01-23 18:38:54 +03:00
|
|
|
|
loadingClientInfo, aController, aSecurityFlags,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
aContentPolicyType, aCookieJarSettings,
|
2019-03-08 12:04:11 +03:00
|
|
|
|
aPerformanceStorage, aLoadGroup, aCallbacks,
|
2020-01-15 11:02:57 +03:00
|
|
|
|
aLoadFlags, aIoService, aSandboxFlags);
|
2017-03-02 17:32:37 +03:00
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsresult NS_NewChannelInternal(
|
|
|
|
|
nsIChannel** outChannel, nsIURI* aUri, nsINode* aLoadingNode,
|
|
|
|
|
nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
|
2018-01-23 18:38:54 +03:00
|
|
|
|
const Maybe<ClientInfo>& aLoadingClientInfo,
|
|
|
|
|
const Maybe<ServiceWorkerDescriptor>& aController,
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
nsICookieJarSettings* aCookieJarSettings /* = nullptr */,
|
2019-03-08 12:04:11 +03:00
|
|
|
|
PerformanceStorage* aPerformanceStorage /* = nullptr */,
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsILoadGroup* aLoadGroup /* = nullptr */,
|
|
|
|
|
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
|
|
|
|
|
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
|
2020-01-15 11:02:57 +03:00
|
|
|
|
nsIIOService* aIoService /* = nullptr */,
|
|
|
|
|
uint32_t aSandboxFlags /* = 0 */) {
|
2017-03-02 17:32:37 +03:00
|
|
|
|
NS_ENSURE_ARG_POINTER(outChannel);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIIOService> grip;
|
|
|
|
|
nsresult rv = net_EnsureIOService(&aIoService, grip);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIChannel> channel;
|
2018-01-23 18:38:54 +03:00
|
|
|
|
rv = aIoService->NewChannelFromURIWithClientAndController(
|
2017-03-02 17:32:37 +03:00
|
|
|
|
aUri, aLoadingNode, aLoadingPrincipal, aTriggeringPrincipal,
|
2018-01-23 18:38:54 +03:00
|
|
|
|
aLoadingClientInfo, aController, aSecurityFlags, aContentPolicyType,
|
2020-01-15 11:02:57 +03:00
|
|
|
|
aSandboxFlags, getter_AddRefs(channel));
|
2017-03-02 17:32:37 +03:00
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aLoadGroup) {
|
|
|
|
|
rv = channel->SetLoadGroup(aLoadGroup);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aCallbacks) {
|
|
|
|
|
rv = channel->SetNotificationCallbacks(aCallbacks);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-30 19:07:59 +03:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
nsLoadFlags channelLoadFlags = 0;
|
|
|
|
|
channel->GetLoadFlags(&channelLoadFlags);
|
|
|
|
|
// Will be removed when we remove LOAD_REPLACE altogether
|
|
|
|
|
// This check is trying to catch protocol handlers that still
|
|
|
|
|
// try to set the LOAD_REPLACE flag.
|
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!(channelLoadFlags & nsIChannel::LOAD_REPLACE));
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
|
2017-05-30 19:07:59 +03:00
|
|
|
|
rv = channel->SetLoadFlags(aLoadFlags);
|
2017-03-02 17:32:37 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-04 11:59:08 +03:00
|
|
|
|
if (aPerformanceStorage || aCookieJarSettings) {
|
2019-02-20 15:27:25 +03:00
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
2019-03-08 12:04:11 +03:00
|
|
|
|
|
|
|
|
|
if (aPerformanceStorage) {
|
|
|
|
|
loadInfo->SetPerformanceStorage(aPerformanceStorage);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-04 11:59:08 +03:00
|
|
|
|
if (aCookieJarSettings) {
|
|
|
|
|
loadInfo->SetCookieJarSettings(aCookieJarSettings);
|
2019-03-08 12:04:11 +03:00
|
|
|
|
}
|
2018-01-24 19:17:31 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
channel.forget(outChannel);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult /*NS_NewChannelWithNodeAndTriggeringPrincipal */
|
|
|
|
|
NS_NewChannelWithTriggeringPrincipal(
|
|
|
|
|
nsIChannel** outChannel, nsIURI* aUri, nsINode* aLoadingNode,
|
|
|
|
|
nsIPrincipal* aTriggeringPrincipal, nsSecurityFlags aSecurityFlags,
|
|
|
|
|
nsContentPolicyType aContentPolicyType,
|
2018-01-24 19:17:31 +03:00
|
|
|
|
PerformanceStorage* aPerformanceStorage /* = nullptr */,
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsILoadGroup* aLoadGroup /* = nullptr */,
|
|
|
|
|
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
|
|
|
|
|
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
|
|
|
|
|
nsIIOService* aIoService /* = nullptr */) {
|
|
|
|
|
MOZ_ASSERT(aLoadingNode);
|
|
|
|
|
NS_ASSERTION(aTriggeringPrincipal,
|
|
|
|
|
"Can not create channel without a triggering Principal!");
|
|
|
|
|
return NS_NewChannelInternal(
|
|
|
|
|
outChannel, aUri, aLoadingNode, aLoadingNode->NodePrincipal(),
|
|
|
|
|
aTriggeringPrincipal, Maybe<ClientInfo>(),
|
2018-01-23 18:38:54 +03:00
|
|
|
|
Maybe<ServiceWorkerDescriptor>(), aSecurityFlags, aContentPolicyType,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
aLoadingNode->OwnerDoc()->CookieJarSettings(), aPerformanceStorage,
|
2019-03-08 12:04:11 +03:00
|
|
|
|
aLoadGroup, aCallbacks, aLoadFlags, aIoService);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// See NS_NewChannelInternal for usage and argument description
|
|
|
|
|
nsresult NS_NewChannelWithTriggeringPrincipal(
|
|
|
|
|
nsIChannel** outChannel, nsIURI* aUri, nsIPrincipal* aLoadingPrincipal,
|
|
|
|
|
nsIPrincipal* aTriggeringPrincipal, nsSecurityFlags aSecurityFlags,
|
|
|
|
|
nsContentPolicyType aContentPolicyType,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
nsICookieJarSettings* aCookieJarSettings /* = nullptr */,
|
2018-01-24 19:17:31 +03:00
|
|
|
|
PerformanceStorage* aPerformanceStorage /* = nullptr */,
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsILoadGroup* aLoadGroup /* = nullptr */,
|
|
|
|
|
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
|
|
|
|
|
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
|
|
|
|
|
nsIIOService* aIoService /* = nullptr */) {
|
|
|
|
|
NS_ASSERTION(aLoadingPrincipal,
|
|
|
|
|
"Can not create channel without a loading Principal!");
|
|
|
|
|
return NS_NewChannelInternal(
|
|
|
|
|
outChannel, aUri,
|
|
|
|
|
nullptr, // aLoadingNode
|
|
|
|
|
aLoadingPrincipal, aTriggeringPrincipal, Maybe<ClientInfo>(),
|
2018-01-23 18:38:54 +03:00
|
|
|
|
Maybe<ServiceWorkerDescriptor>(), aSecurityFlags, aContentPolicyType,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
aCookieJarSettings, aPerformanceStorage, aLoadGroup, aCallbacks,
|
|
|
|
|
aLoadFlags, aIoService);
|
2018-01-23 18:38:54 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// See NS_NewChannelInternal for usage and argument description
|
|
|
|
|
nsresult NS_NewChannelWithTriggeringPrincipal(
|
|
|
|
|
nsIChannel** outChannel, nsIURI* aUri, nsIPrincipal* aLoadingPrincipal,
|
|
|
|
|
nsIPrincipal* aTriggeringPrincipal, const ClientInfo& aLoadingClientInfo,
|
|
|
|
|
const Maybe<ServiceWorkerDescriptor>& aController,
|
|
|
|
|
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
nsICookieJarSettings* aCookieJarSettings /* = nullptr */,
|
2018-01-24 19:17:31 +03:00
|
|
|
|
PerformanceStorage* aPerformanceStorage /* = nullptr */,
|
2018-01-23 18:38:54 +03:00
|
|
|
|
nsILoadGroup* aLoadGroup /* = nullptr */,
|
|
|
|
|
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
|
|
|
|
|
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
|
|
|
|
|
nsIIOService* aIoService /* = nullptr */) {
|
|
|
|
|
AssertLoadingPrincipalAndClientInfoMatch(
|
|
|
|
|
aLoadingPrincipal, aLoadingClientInfo, aContentPolicyType);
|
|
|
|
|
|
|
|
|
|
Maybe<ClientInfo> loadingClientInfo;
|
|
|
|
|
loadingClientInfo.emplace(aLoadingClientInfo);
|
|
|
|
|
|
2019-03-08 12:04:11 +03:00
|
|
|
|
return NS_NewChannelInternal(
|
|
|
|
|
outChannel, aUri,
|
|
|
|
|
nullptr, // aLoadingNode
|
|
|
|
|
aLoadingPrincipal, aTriggeringPrincipal, loadingClientInfo, aController,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
aSecurityFlags, aContentPolicyType, aCookieJarSettings,
|
|
|
|
|
aPerformanceStorage, aLoadGroup, aCallbacks, aLoadFlags, aIoService);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult NS_NewChannel(nsIChannel** outChannel, nsIURI* aUri,
|
|
|
|
|
nsINode* aLoadingNode, nsSecurityFlags aSecurityFlags,
|
|
|
|
|
nsContentPolicyType aContentPolicyType,
|
2018-01-24 19:17:31 +03:00
|
|
|
|
PerformanceStorage* aPerformanceStorage /* = nullptr */,
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsILoadGroup* aLoadGroup /* = nullptr */,
|
|
|
|
|
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
|
|
|
|
|
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
|
2020-01-15 11:02:57 +03:00
|
|
|
|
nsIIOService* aIoService /* = nullptr */,
|
|
|
|
|
uint32_t aSandboxFlags /* = 0 */) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
NS_ASSERTION(aLoadingNode, "Can not create channel without a loading Node!");
|
|
|
|
|
return NS_NewChannelInternal(
|
|
|
|
|
outChannel, aUri, aLoadingNode, aLoadingNode->NodePrincipal(),
|
|
|
|
|
nullptr, // aTriggeringPrincipal
|
2018-01-23 18:38:54 +03:00
|
|
|
|
Maybe<ClientInfo>(), Maybe<ServiceWorkerDescriptor>(), aSecurityFlags,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
aContentPolicyType, aLoadingNode->OwnerDoc()->CookieJarSettings(),
|
2020-01-15 11:02:57 +03:00
|
|
|
|
aPerformanceStorage, aLoadGroup, aCallbacks, aLoadFlags, aIoService,
|
|
|
|
|
aSandboxFlags);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-04-20 05:15:06 +03:00
|
|
|
|
nsresult NS_GetIsDocumentChannel(nsIChannel* aChannel, bool* aIsDocument) {
|
|
|
|
|
// Check if this channel is going to be used to create a document. If it has
|
|
|
|
|
// LOAD_DOCUMENT_URI set it is trivially creating a document. If
|
|
|
|
|
// LOAD_HTML_OBJECT_DATA is set it may or may not be used to create a
|
|
|
|
|
// document, depending on its MIME type.
|
|
|
|
|
|
|
|
|
|
if (!aChannel || !aIsDocument) {
|
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
}
|
2017-04-25 14:38:03 +03:00
|
|
|
|
*aIsDocument = false;
|
2017-04-20 05:15:06 +03:00
|
|
|
|
nsLoadFlags loadFlags;
|
|
|
|
|
nsresult rv = aChannel->GetLoadFlags(&loadFlags);
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
|
|
|
|
|
*aIsDocument = true;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
if (!(loadFlags & nsIRequest::LOAD_HTML_OBJECT_DATA)) {
|
|
|
|
|
*aIsDocument = false;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
nsAutoCString mimeType;
|
|
|
|
|
rv = aChannel->GetContentType(mimeType);
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
2021-09-09 18:03:05 +03:00
|
|
|
|
if (nsContentUtils::HtmlObjectContentTypeForMIMEType(mimeType, false) ==
|
|
|
|
|
nsIObjectLoadingContent::TYPE_DOCUMENT) {
|
2017-04-20 05:15:06 +03:00
|
|
|
|
*aIsDocument = true;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
*aIsDocument = false;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult NS_MakeAbsoluteURI(nsACString& result, const nsACString& spec,
|
|
|
|
|
nsIURI* baseURI) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
if (!baseURI) {
|
|
|
|
|
NS_WARNING("It doesn't make sense to not supply a base URI");
|
|
|
|
|
result = spec;
|
|
|
|
|
rv = NS_OK;
|
2021-06-04 15:35:16 +03:00
|
|
|
|
} else if (spec.IsEmpty()) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
rv = baseURI->GetSpec(result);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
} else {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
rv = baseURI->Resolve(spec, result);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
}
|
2017-03-02 17:32:37 +03:00
|
|
|
|
return rv;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult NS_MakeAbsoluteURI(char** result, const char* spec, nsIURI* baseURI) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsAutoCString resultBuf;
|
|
|
|
|
rv = NS_MakeAbsoluteURI(resultBuf, nsDependentCString(spec), baseURI);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2020-05-17 09:58:48 +03:00
|
|
|
|
*result = ToNewCString(resultBuf, mozilla::fallible);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (!*result) rv = NS_ERROR_OUT_OF_MEMORY;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_MakeAbsoluteURI(nsAString& result, const nsAString& spec,
|
|
|
|
|
nsIURI* baseURI) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
if (!baseURI) {
|
|
|
|
|
NS_WARNING("It doesn't make sense to not supply a base URI");
|
|
|
|
|
result = spec;
|
|
|
|
|
rv = NS_OK;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
} else {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsAutoCString resultBuf;
|
2021-06-04 15:35:16 +03:00
|
|
|
|
if (spec.IsEmpty()) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
rv = baseURI->GetSpec(resultBuf);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
} else {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
rv = baseURI->Resolve(NS_ConvertUTF16toUTF8(spec), resultBuf);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) CopyUTF8toUTF16(resultBuf, result);
|
|
|
|
|
}
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t NS_GetDefaultPort(const char* scheme,
|
|
|
|
|
nsIIOService* ioService /* = nullptr */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
|
2017-05-07 01:49:19 +03:00
|
|
|
|
// Getting the default port through the protocol handler has a lot of XPCOM
|
|
|
|
|
// overhead involved. We optimize the protocols that matter for Web pages
|
|
|
|
|
// (HTTP and HTTPS) by hardcoding their default ports here.
|
|
|
|
|
if (strncmp(scheme, "http", 4) == 0) {
|
|
|
|
|
if (scheme[4] == 's' && scheme[5] == '\0') {
|
|
|
|
|
return 443;
|
|
|
|
|
}
|
|
|
|
|
if (scheme[4] == '\0') {
|
|
|
|
|
return 80;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsCOMPtr<nsIIOService> grip;
|
|
|
|
|
net_EnsureIOService(&ioService, grip);
|
|
|
|
|
if (!ioService) return -1;
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIProtocolHandler> handler;
|
|
|
|
|
rv = ioService->GetProtocolHandler(scheme, getter_AddRefs(handler));
|
|
|
|
|
if (NS_FAILED(rv)) return -1;
|
|
|
|
|
int32_t port;
|
|
|
|
|
rv = handler->GetDefaultPort(&port);
|
|
|
|
|
return NS_SUCCEEDED(rv) ? port : -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function is a helper function to apply the ToAscii conversion
|
|
|
|
|
* to a string
|
|
|
|
|
*/
|
|
|
|
|
bool NS_StringToACE(const nsACString& idn, nsACString& result) {
|
|
|
|
|
nsCOMPtr<nsIIDNService> idnSrv = do_GetService(NS_IDNSERVICE_CONTRACTID);
|
|
|
|
|
if (!idnSrv) return false;
|
|
|
|
|
nsresult rv = idnSrv->ConvertUTF8toACE(idn, result);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
return NS_SUCCEEDED(rv);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t NS_GetRealPort(nsIURI* aURI) {
|
|
|
|
|
int32_t port;
|
|
|
|
|
nsresult rv = aURI->GetPort(&port);
|
|
|
|
|
if (NS_FAILED(rv)) return -1;
|
|
|
|
|
|
|
|
|
|
if (port != -1) return port; // explicitly specified
|
|
|
|
|
|
|
|
|
|
// Otherwise, we have to get the default port from the protocol handler
|
|
|
|
|
|
|
|
|
|
// Need the scheme first
|
|
|
|
|
nsAutoCString scheme;
|
|
|
|
|
rv = aURI->GetScheme(scheme);
|
|
|
|
|
if (NS_FAILED(rv)) return -1;
|
|
|
|
|
|
|
|
|
|
return NS_GetDefaultPort(scheme.get());
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-22 13:18:18 +03:00
|
|
|
|
nsresult NS_NewInputStreamChannelInternal(
|
|
|
|
|
nsIChannel** outChannel, nsIURI* aUri,
|
|
|
|
|
already_AddRefed<nsIInputStream> aStream, const nsACString& aContentType,
|
|
|
|
|
const nsACString& aContentCharset, nsILoadInfo* aLoadInfo) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIInputStreamChannel> isc =
|
|
|
|
|
do_CreateInstance(NS_INPUTSTREAMCHANNEL_CONTRACTID, &rv);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
rv = isc->SetURI(aUri);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2017-11-22 13:18:18 +03:00
|
|
|
|
|
2018-05-30 22:15:35 +03:00
|
|
|
|
nsCOMPtr<nsIInputStream> stream = std::move(aStream);
|
2017-11-22 13:18:18 +03:00
|
|
|
|
rv = isc->SetContentStream(stream);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIChannel> channel = do_QueryInterface(isc, &rv);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
if (!aContentType.IsEmpty()) {
|
|
|
|
|
rv = channel->SetContentType(aContentType);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!aContentCharset.IsEmpty()) {
|
|
|
|
|
rv = channel->SetContentCharset(aContentCharset);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-20 15:27:25 +03:00
|
|
|
|
MOZ_ASSERT(aLoadInfo, "need a loadinfo to create a inputstreamchannel");
|
2015-05-20 05:48:00 +03:00
|
|
|
|
channel->SetLoadInfo(aLoadInfo);
|
|
|
|
|
|
|
|
|
|
// If we're sandboxed, make sure to clear any owner the channel
|
|
|
|
|
// might already have.
|
|
|
|
|
if (aLoadInfo && aLoadInfo->GetLoadingSandboxed()) {
|
|
|
|
|
channel->SetOwner(nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
channel.forget(outChannel);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-22 13:18:18 +03:00
|
|
|
|
nsresult NS_NewInputStreamChannelInternal(
|
|
|
|
|
nsIChannel** outChannel, nsIURI* aUri,
|
|
|
|
|
already_AddRefed<nsIInputStream> aStream, const nsACString& aContentType,
|
|
|
|
|
const nsACString& aContentCharset, nsINode* aLoadingNode,
|
|
|
|
|
nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
|
2015-08-19 20:43:30 +03:00
|
|
|
|
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType) {
|
2018-05-30 22:21:17 +03:00
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = new mozilla::net::LoadInfo(
|
|
|
|
|
aLoadingPrincipal, aTriggeringPrincipal, aLoadingNode, aSecurityFlags,
|
|
|
|
|
aContentPolicyType);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (!loadInfo) {
|
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
}
|
2017-11-22 13:18:18 +03:00
|
|
|
|
|
2018-05-30 22:15:35 +03:00
|
|
|
|
nsCOMPtr<nsIInputStream> stream = std::move(aStream);
|
2017-11-22 13:18:18 +03:00
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return NS_NewInputStreamChannelInternal(outChannel, aUri, stream.forget(),
|
|
|
|
|
aContentType, aContentCharset,
|
|
|
|
|
loadInfo);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-22 13:18:36 +03:00
|
|
|
|
nsresult NS_NewInputStreamChannel(
|
|
|
|
|
nsIChannel** outChannel, nsIURI* aUri,
|
|
|
|
|
already_AddRefed<nsIInputStream> aStream, nsIPrincipal* aLoadingPrincipal,
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
|
2020-09-23 18:17:15 +03:00
|
|
|
|
const nsACString& aContentType /* = ""_ns */,
|
|
|
|
|
const nsACString& aContentCharset /* = ""_ns */) {
|
2017-11-22 13:18:18 +03:00
|
|
|
|
nsCOMPtr<nsIInputStream> stream = aStream;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return NS_NewInputStreamChannelInternal(outChannel, aUri, stream.forget(),
|
|
|
|
|
aContentType, aContentCharset,
|
|
|
|
|
nullptr, // aLoadingNode
|
|
|
|
|
aLoadingPrincipal,
|
|
|
|
|
nullptr, // aTriggeringPrincipal
|
|
|
|
|
aSecurityFlags, aContentPolicyType);
|
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult NS_NewInputStreamChannelInternal(nsIChannel** outChannel, nsIURI* aUri,
|
|
|
|
|
const nsAString& aData,
|
|
|
|
|
const nsACString& aContentType,
|
2016-03-04 19:54:07 +03:00
|
|
|
|
nsILoadInfo* aLoadInfo,
|
2015-08-19 20:43:30 +03:00
|
|
|
|
bool aIsSrcdocChannel /* = false */) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIStringInputStream> stream;
|
|
|
|
|
stream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
uint32_t len;
|
|
|
|
|
char* utf8Bytes = ToNewUTF8String(aData, &len);
|
|
|
|
|
rv = stream->AdoptData(utf8Bytes, len);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIChannel> channel;
|
|
|
|
|
rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aUri,
|
2017-11-22 13:18:18 +03:00
|
|
|
|
stream.forget(), aContentType,
|
2015-05-20 05:48:00 +03:00
|
|
|
|
"UTF-8"_ns, aLoadInfo);
|
|
|
|
|
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
if (aIsSrcdocChannel) {
|
|
|
|
|
nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(channel);
|
|
|
|
|
NS_ENSURE_TRUE(inStrmChan, NS_ERROR_FAILURE);
|
|
|
|
|
inStrmChan->SetSrcdocData(aData);
|
|
|
|
|
}
|
|
|
|
|
channel.forget(outChannel);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-04 19:54:07 +03:00
|
|
|
|
nsresult NS_NewInputStreamChannelInternal(
|
|
|
|
|
nsIChannel** outChannel, nsIURI* aUri, const nsAString& aData,
|
|
|
|
|
const nsACString& aContentType, nsINode* aLoadingNode,
|
|
|
|
|
nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
|
|
|
|
|
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
|
|
|
|
|
bool aIsSrcdocChannel /* = false */) {
|
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = new mozilla::net::LoadInfo(
|
2018-05-30 22:21:17 +03:00
|
|
|
|
aLoadingPrincipal, aTriggeringPrincipal, aLoadingNode, aSecurityFlags,
|
|
|
|
|
aContentPolicyType);
|
2016-03-04 19:54:07 +03:00
|
|
|
|
return NS_NewInputStreamChannelInternal(outChannel, aUri, aData, aContentType,
|
|
|
|
|
loadInfo, aIsSrcdocChannel);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult NS_NewInputStreamChannel(nsIChannel** outChannel, nsIURI* aUri,
|
|
|
|
|
const nsAString& aData,
|
|
|
|
|
const nsACString& aContentType,
|
|
|
|
|
nsIPrincipal* aLoadingPrincipal,
|
|
|
|
|
nsSecurityFlags aSecurityFlags,
|
|
|
|
|
nsContentPolicyType aContentPolicyType,
|
2015-08-19 20:43:30 +03:00
|
|
|
|
bool aIsSrcdocChannel /* = false */) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return NS_NewInputStreamChannelInternal(outChannel, aUri, aData, aContentType,
|
|
|
|
|
nullptr, // aLoadingNode
|
|
|
|
|
aLoadingPrincipal,
|
|
|
|
|
nullptr, // aTriggeringPrincipal
|
|
|
|
|
aSecurityFlags, aContentPolicyType,
|
2015-08-19 20:43:30 +03:00
|
|
|
|
aIsSrcdocChannel);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-22 13:18:57 +03:00
|
|
|
|
nsresult NS_NewInputStreamPump(
|
|
|
|
|
nsIInputStreamPump** aResult, already_AddRefed<nsIInputStream> aStream,
|
|
|
|
|
uint32_t aSegsize /* = 0 */, uint32_t aSegcount /* = 0 */,
|
|
|
|
|
bool aCloseWhenDone /* = false */,
|
|
|
|
|
nsIEventTarget* aMainThreadTarget /* = nullptr */) {
|
2018-05-30 22:15:35 +03:00
|
|
|
|
nsCOMPtr<nsIInputStream> stream = std::move(aStream);
|
2017-11-22 13:18:57 +03:00
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIInputStreamPump> pump =
|
|
|
|
|
do_CreateInstance(NS_INPUTSTREAMPUMP_CONTRACTID, &rv);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2017-11-22 13:18:57 +03:00
|
|
|
|
rv = pump->Init(stream, aSegsize, aSegcount, aCloseWhenDone,
|
|
|
|
|
aMainThreadTarget);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2017-11-22 13:18:57 +03:00
|
|
|
|
*aResult = nullptr;
|
|
|
|
|
pump.swap(*aResult);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewLoadGroup(nsILoadGroup** result, nsIRequestObserver* obs) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsILoadGroup> group =
|
|
|
|
|
do_CreateInstance(NS_LOADGROUP_CONTRACTID, &rv);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
rv = group->SetGroupObserver(obs);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
*result = nullptr;
|
|
|
|
|
group.swap(*result);
|
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NS_IsReasonableHTTPHeaderValue(const nsACString& aValue) {
|
2014-07-24 20:38:55 +04:00
|
|
|
|
return mozilla::net::nsHttp::IsReasonableHeaderValue(aValue);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
bool NS_IsValidHTTPToken(const nsACString& aToken) {
|
2014-07-24 20:38:55 +04:00
|
|
|
|
return mozilla::net::nsHttp::IsValidToken(aToken);
|
|
|
|
|
}
|
2014-12-15 16:39:00 +03:00
|
|
|
|
|
2017-04-10 11:15:29 +03:00
|
|
|
|
void NS_TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest) {
|
|
|
|
|
mozilla::net::nsHttp::TrimHTTPWhitespace(aSource, aDest);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult NS_NewLoadGroup(nsILoadGroup** aResult, nsIPrincipal* aPrincipal) {
|
2014-12-15 16:39:00 +03:00
|
|
|
|
using mozilla::LoadContext;
|
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsILoadGroup> group =
|
|
|
|
|
do_CreateInstance(NS_LOADGROUP_CONTRACTID, &rv);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<LoadContext> loadContext = new LoadContext(aPrincipal);
|
2014-12-15 16:39:00 +03:00
|
|
|
|
rv = group->SetNotificationCallbacks(loadContext);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
group.forget(aResult);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
bool NS_LoadGroupMatchesPrincipal(nsILoadGroup* aLoadGroup,
|
|
|
|
|
nsIPrincipal* aPrincipal) {
|
2014-12-15 16:39:00 +03:00
|
|
|
|
if (!aPrincipal) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If this is a null principal then the load group doesn't really matter.
|
|
|
|
|
// The principal will not be allowed to perform any actions that actually
|
|
|
|
|
// use the load group. Unconditionally treat null principals as a match.
|
2016-08-12 08:19:29 +03:00
|
|
|
|
if (aPrincipal->GetIsNullPrincipal()) {
|
2014-12-15 16:39:00 +03:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!aLoadGroup) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsILoadContext> loadContext;
|
|
|
|
|
NS_QueryNotificationCallbacks(nullptr, aLoadGroup, NS_GET_IID(nsILoadContext),
|
|
|
|
|
getter_AddRefs(loadContext));
|
|
|
|
|
NS_ENSURE_TRUE(loadContext, false);
|
|
|
|
|
|
2019-07-17 02:40:19 +03:00
|
|
|
|
return true;
|
2014-12-15 16:39:00 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
nsresult NS_NewDownloader(nsIStreamListener** result,
|
|
|
|
|
nsIDownloadObserver* observer,
|
|
|
|
|
nsIFile* downloadLocation /* = nullptr */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIDownloader> downloader =
|
|
|
|
|
do_CreateInstance(NS_DOWNLOADER_CONTRACTID, &rv);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
rv = downloader->Init(observer, downloadLocation);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
downloader.forget(result);
|
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-30 17:54:11 +03:00
|
|
|
|
nsresult NS_NewIncrementalStreamLoader(
|
|
|
|
|
nsIIncrementalStreamLoader** result,
|
|
|
|
|
nsIIncrementalStreamLoaderObserver* observer) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIIncrementalStreamLoader> loader =
|
|
|
|
|
do_CreateInstance(NS_INCREMENTALSTREAMLOADER_CONTRACTID, &rv);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2015-11-30 17:54:11 +03:00
|
|
|
|
rv = loader->Init(observer);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
*result = nullptr;
|
|
|
|
|
loader.swap(*result);
|
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2015-11-30 17:54:11 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsresult NS_NewStreamLoader(
|
|
|
|
|
nsIStreamLoader** result, nsIStreamLoaderObserver* observer,
|
|
|
|
|
nsIRequestObserver* requestObserver /* = nullptr */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIStreamLoader> loader =
|
|
|
|
|
do_CreateInstance(NS_STREAMLOADER_CONTRACTID, &rv);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2017-03-02 17:32:37 +03:00
|
|
|
|
rv = loader->Init(observer, requestObserver);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
*result = nullptr;
|
|
|
|
|
loader.swap(*result);
|
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-03-02 17:32:37 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult NS_NewStreamLoaderInternal(
|
|
|
|
|
nsIStreamLoader** outStream, nsIURI* aUri,
|
|
|
|
|
nsIStreamLoaderObserver* aObserver, nsINode* aLoadingNode,
|
|
|
|
|
nsIPrincipal* aLoadingPrincipal, nsSecurityFlags aSecurityFlags,
|
|
|
|
|
nsContentPolicyType aContentPolicyType,
|
|
|
|
|
nsILoadGroup* aLoadGroup /* = nullptr */,
|
|
|
|
|
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
|
2019-05-02 15:34:52 +03:00
|
|
|
|
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsCOMPtr<nsIChannel> channel;
|
|
|
|
|
nsresult rv = NS_NewChannelInternal(
|
|
|
|
|
getter_AddRefs(channel), aUri, aLoadingNode, aLoadingPrincipal,
|
|
|
|
|
nullptr, // aTriggeringPrincipal
|
2018-01-23 18:38:54 +03:00
|
|
|
|
Maybe<ClientInfo>(), Maybe<ServiceWorkerDescriptor>(), aSecurityFlags,
|
2015-05-20 05:48:00 +03:00
|
|
|
|
aContentPolicyType,
|
2020-03-04 11:59:08 +03:00
|
|
|
|
nullptr, // nsICookieJarSettings
|
2018-01-24 19:17:31 +03:00
|
|
|
|
nullptr, // PerformanceStorage
|
2015-05-20 05:48:00 +03:00
|
|
|
|
aLoadGroup, aCallbacks, aLoadFlags);
|
|
|
|
|
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
rv = NS_NewStreamLoader(outStream, aObserver);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2019-02-12 19:08:25 +03:00
|
|
|
|
return channel->AsyncOpen(*outStream);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewStreamLoader(
|
|
|
|
|
nsIStreamLoader** outStream, nsIURI* aUri,
|
|
|
|
|
nsIStreamLoaderObserver* aObserver, nsINode* aLoadingNode,
|
|
|
|
|
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
|
|
|
|
|
nsILoadGroup* aLoadGroup /* = nullptr */,
|
|
|
|
|
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
|
2019-05-02 15:34:52 +03:00
|
|
|
|
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
NS_ASSERTION(aLoadingNode,
|
|
|
|
|
"Can not create stream loader without a loading Node!");
|
|
|
|
|
return NS_NewStreamLoaderInternal(
|
|
|
|
|
outStream, aUri, aObserver, aLoadingNode, aLoadingNode->NodePrincipal(),
|
2019-05-02 15:34:52 +03:00
|
|
|
|
aSecurityFlags, aContentPolicyType, aLoadGroup, aCallbacks, aLoadFlags);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult NS_NewStreamLoader(
|
|
|
|
|
nsIStreamLoader** outStream, nsIURI* aUri,
|
|
|
|
|
nsIStreamLoaderObserver* aObserver, nsIPrincipal* aLoadingPrincipal,
|
|
|
|
|
nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
|
|
|
|
|
nsILoadGroup* aLoadGroup /* = nullptr */,
|
|
|
|
|
nsIInterfaceRequestor* aCallbacks /* = nullptr */,
|
2019-05-02 15:34:52 +03:00
|
|
|
|
nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return NS_NewStreamLoaderInternal(outStream, aUri, aObserver,
|
|
|
|
|
nullptr, // aLoadingNode
|
|
|
|
|
aLoadingPrincipal, aSecurityFlags,
|
|
|
|
|
aContentPolicyType, aLoadGroup, aCallbacks,
|
2019-05-02 15:34:52 +03:00
|
|
|
|
aLoadFlags);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult NS_NewSyncStreamListener(nsIStreamListener** result,
|
|
|
|
|
nsIInputStream** stream) {
|
2018-10-23 23:07:29 +03:00
|
|
|
|
nsCOMPtr<nsISyncStreamListener> listener = nsSyncStreamListener::Create();
|
|
|
|
|
if (listener) {
|
|
|
|
|
nsresult rv = listener->GetInputStream(stream);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
listener.forget(result);
|
|
|
|
|
}
|
2018-10-23 23:07:29 +03:00
|
|
|
|
return rv;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2018-10-23 23:07:29 +03:00
|
|
|
|
return NS_ERROR_FAILURE;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_ImplementChannelOpen(nsIChannel* channel, nsIInputStream** result) {
|
|
|
|
|
nsCOMPtr<nsIStreamListener> listener;
|
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
|
|
|
|
nsresult rv = NS_NewSyncStreamListener(getter_AddRefs(listener),
|
|
|
|
|
getter_AddRefs(stream));
|
2016-05-12 20:38:59 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
2019-02-12 19:08:25 +03:00
|
|
|
|
rv = NS_MaybeOpenChannelUsingAsyncOpen(channel, listener);
|
2016-05-12 20:38:59 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
uint64_t n;
|
|
|
|
|
// block until the initial response is received or an error occurs.
|
|
|
|
|
rv = stream->Available(&n);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
*result = nullptr;
|
|
|
|
|
stream.swap(*result);
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
nsresult NS_NewRequestObserverProxy(nsIRequestObserver** result,
|
|
|
|
|
nsIRequestObserver* observer,
|
|
|
|
|
nsISupports* context) {
|
2018-10-23 23:07:19 +03:00
|
|
|
|
nsCOMPtr<nsIRequestObserverProxy> proxy = new nsRequestObserverProxy();
|
|
|
|
|
nsresult rv = proxy->Init(observer, context);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2018-10-23 23:07:19 +03:00
|
|
|
|
proxy.forget(result);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewSimpleStreamListener(
|
|
|
|
|
nsIStreamListener** result, nsIOutputStream* sink,
|
|
|
|
|
nsIRequestObserver* observer /* = nullptr */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsISimpleStreamListener> listener =
|
|
|
|
|
do_CreateInstance(NS_SIMPLESTREAMLISTENER_CONTRACTID, &rv);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
rv = listener->Init(sink, observer);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
listener.forget(result);
|
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_CheckPortSafety(int32_t port, const char* scheme,
|
|
|
|
|
nsIIOService* ioService /* = nullptr */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIIOService> grip;
|
|
|
|
|
rv = net_EnsureIOService(&ioService, grip);
|
|
|
|
|
if (ioService) {
|
|
|
|
|
bool allow;
|
|
|
|
|
rv = ioService->AllowPort(port, scheme, &allow);
|
|
|
|
|
if (NS_SUCCEEDED(rv) && !allow) {
|
|
|
|
|
NS_WARNING("port blocked");
|
|
|
|
|
rv = NS_ERROR_PORT_ACCESS_NOT_ALLOWED;
|
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_CheckPortSafety(nsIURI* uri) {
|
|
|
|
|
int32_t port;
|
|
|
|
|
nsresult rv = uri->GetPort(&port);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
if (NS_FAILED(rv) || port == -1) { // port undefined or default-valued
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return NS_OK;
|
2021-06-04 15:35:16 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsAutoCString scheme;
|
|
|
|
|
uri->GetScheme(scheme);
|
|
|
|
|
return NS_CheckPortSafety(port, scheme.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewProxyInfo(const nsACString& type, const nsACString& host,
|
|
|
|
|
int32_t port, uint32_t flags, nsIProxyInfo** result) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIProtocolProxyService> pps =
|
|
|
|
|
do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2020-09-23 18:17:15 +03:00
|
|
|
|
rv = pps->NewProxyInfo(type, host, port, ""_ns, ""_ns, flags, UINT32_MAX,
|
|
|
|
|
nullptr, result);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_GetFileProtocolHandler(nsIFileProtocolHandler** result,
|
|
|
|
|
nsIIOService* ioService /* = nullptr */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIIOService> grip;
|
|
|
|
|
rv = net_EnsureIOService(&ioService, grip);
|
|
|
|
|
if (ioService) {
|
|
|
|
|
nsCOMPtr<nsIProtocolHandler> handler;
|
|
|
|
|
rv = ioService->GetProtocolHandler("file", getter_AddRefs(handler));
|
|
|
|
|
if (NS_SUCCEEDED(rv)) rv = CallQueryInterface(handler, result);
|
|
|
|
|
}
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_GetFileFromURLSpec(const nsACString& inURL, nsIFile** result,
|
|
|
|
|
nsIIOService* ioService /* = nullptr */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIFileProtocolHandler> fileHandler;
|
|
|
|
|
rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) rv = fileHandler->GetFileFromURLSpec(inURL, result);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_GetURLSpecFromFile(nsIFile* file, nsACString& url,
|
|
|
|
|
nsIIOService* ioService /* = nullptr */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIFileProtocolHandler> fileHandler;
|
|
|
|
|
rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) rv = fileHandler->GetURLSpecFromFile(file, url);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_GetURLSpecFromActualFile(nsIFile* file, nsACString& url,
|
|
|
|
|
nsIIOService* ioService /* = nullptr */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIFileProtocolHandler> fileHandler;
|
|
|
|
|
rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) rv = fileHandler->GetURLSpecFromActualFile(file, url);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_GetURLSpecFromDir(nsIFile* file, nsACString& url,
|
|
|
|
|
nsIIOService* ioService /* = nullptr */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIFileProtocolHandler> fileHandler;
|
|
|
|
|
rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler), ioService);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) rv = fileHandler->GetURLSpecFromDir(file, url);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-02 15:34:52 +03:00
|
|
|
|
void NS_GetReferrerFromChannel(nsIChannel* channel, nsIURI** referrer) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
*referrer = nullptr;
|
|
|
|
|
|
2021-03-25 22:47:02 +03:00
|
|
|
|
if (nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(channel)) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
// We have to check for a property on a property bag because the
|
|
|
|
|
// referrer may be empty for security reasons (for example, when loading
|
|
|
|
|
// an http page with an https referrer).
|
2021-03-25 22:47:02 +03:00
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIURI> uri(
|
|
|
|
|
do_GetProperty(props, u"docshell.internalReferrer"_ns, &rv));
|
2019-09-16 10:22:17 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2021-03-25 22:47:02 +03:00
|
|
|
|
uri.forget(referrer);
|
2019-09-16 10:22:17 +03:00
|
|
|
|
return;
|
|
|
|
|
}
|
2019-05-02 15:34:52 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
// if that didn't work, we can still try to get the referrer from the
|
2015-05-20 05:48:00 +03:00
|
|
|
|
// nsIHttpChannel (if we can QI to it)
|
2019-05-02 15:34:52 +03:00
|
|
|
|
nsCOMPtr<nsIHttpChannel> chan(do_QueryInterface(channel));
|
|
|
|
|
if (!chan) {
|
|
|
|
|
return;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2019-05-02 15:34:52 +03:00
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIReferrerInfo> referrerInfo = chan->GetReferrerInfo();
|
|
|
|
|
if (!referrerInfo) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
referrerInfo->GetOriginalReferrer(referrer);
|
2017-03-02 17:32:37 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-01 21:36:19 +03:00
|
|
|
|
already_AddRefed<nsINetUtil> do_GetNetUtil(nsresult* error /* = 0 */) {
|
2021-02-18 16:26:32 +03:00
|
|
|
|
nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service();
|
2015-10-01 21:36:19 +03:00
|
|
|
|
nsCOMPtr<nsINetUtil> util;
|
|
|
|
|
if (io) util = do_QueryInterface(io);
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (error) *error = !!util ? NS_OK : NS_ERROR_FAILURE;
|
|
|
|
|
return util.forget();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_ParseRequestContentType(const nsACString& rawContentType,
|
2015-10-01 21:36:19 +03:00
|
|
|
|
nsCString& contentType,
|
|
|
|
|
nsCString& contentCharset) {
|
|
|
|
|
// contentCharset is left untouched if not present in rawContentType
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult rv;
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2015-10-01 21:36:19 +03:00
|
|
|
|
nsCString charset;
|
|
|
|
|
bool hadCharset;
|
2015-10-01 19:50:13 +03:00
|
|
|
|
rv = util->ParseRequestContentType(rawContentType, charset, &hadCharset,
|
2015-10-01 21:36:19 +03:00
|
|
|
|
contentType);
|
|
|
|
|
if (NS_SUCCEEDED(rv) && hadCharset) contentCharset = charset;
|
2018-10-23 23:07:29 +03:00
|
|
|
|
return rv;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-01 19:51:50 +03:00
|
|
|
|
nsresult NS_ParseResponseContentType(const nsACString& rawContentType,
|
2015-10-01 21:36:19 +03:00
|
|
|
|
nsCString& contentType,
|
|
|
|
|
nsCString& contentCharset) {
|
|
|
|
|
// contentCharset is left untouched if not present in rawContentType
|
|
|
|
|
nsresult rv;
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2015-10-01 21:36:19 +03:00
|
|
|
|
nsCString charset;
|
|
|
|
|
bool hadCharset;
|
2015-10-01 19:50:13 +03:00
|
|
|
|
rv = util->ParseResponseContentType(rawContentType, charset, &hadCharset,
|
2015-10-01 21:36:19 +03:00
|
|
|
|
contentType);
|
|
|
|
|
if (NS_SUCCEEDED(rv) && hadCharset) contentCharset = charset;
|
2018-10-23 23:07:29 +03:00
|
|
|
|
return rv;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult NS_ExtractCharsetFromContentType(const nsACString& rawContentType,
|
|
|
|
|
nsCString& contentCharset,
|
|
|
|
|
bool* hadCharset,
|
|
|
|
|
int32_t* charsetStart,
|
|
|
|
|
int32_t* charsetEnd) {
|
|
|
|
|
// contentCharset is left untouched if not present in rawContentType
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
return util->ExtractCharsetFromContentType(
|
|
|
|
|
rawContentType, contentCharset, charsetStart, charsetEnd, hadCharset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewAtomicFileOutputStream(nsIOutputStream** result, nsIFile* file,
|
|
|
|
|
int32_t ioFlags /* = -1 */,
|
|
|
|
|
int32_t perm /* = -1 */,
|
|
|
|
|
int32_t behaviorFlags /* = 0 */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIFileOutputStream> out =
|
|
|
|
|
do_CreateInstance(NS_ATOMICLOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
rv = out->Init(file, ioFlags, perm, behaviorFlags);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) out.forget(result);
|
|
|
|
|
}
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewSafeLocalFileOutputStream(nsIOutputStream** result,
|
|
|
|
|
nsIFile* file,
|
|
|
|
|
int32_t ioFlags /* = -1 */,
|
|
|
|
|
int32_t perm /* = -1 */,
|
|
|
|
|
int32_t behaviorFlags /* = 0 */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIFileOutputStream> out =
|
|
|
|
|
do_CreateInstance(NS_SAFELOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
rv = out->Init(file, ioFlags, perm, behaviorFlags);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) out.forget(result);
|
|
|
|
|
}
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewLocalFileStream(nsIFileStream** result, nsIFile* file,
|
|
|
|
|
int32_t ioFlags /* = -1 */,
|
|
|
|
|
int32_t perm /* = -1 */,
|
|
|
|
|
int32_t behaviorFlags /* = 0 */) {
|
2018-09-10 02:18:19 +03:00
|
|
|
|
nsCOMPtr<nsIFileStream> stream = new nsFileStream();
|
|
|
|
|
nsresult rv = stream->Init(file, ioFlags, perm, behaviorFlags);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2018-09-10 02:18:19 +03:00
|
|
|
|
stream.forget(result);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-17 22:30:05 +03:00
|
|
|
|
mozilla::Result<nsCOMPtr<nsIFileStream>, nsresult> NS_NewLocalFileStream(
|
|
|
|
|
nsIFile* file, int32_t ioFlags /* = -1 */, int32_t perm /* = -1 */,
|
|
|
|
|
int32_t behaviorFlags /* = 0 */) {
|
|
|
|
|
nsCOMPtr<nsIFileStream> stream;
|
|
|
|
|
const nsresult rv = NS_NewLocalFileStream(getter_AddRefs(stream), file,
|
|
|
|
|
ioFlags, perm, behaviorFlags);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
return stream;
|
|
|
|
|
}
|
|
|
|
|
return Err(rv);
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-24 15:38:23 +03:00
|
|
|
|
nsresult NS_NewBufferedOutputStream(
|
|
|
|
|
nsIOutputStream** aResult, already_AddRefed<nsIOutputStream> aOutputStream,
|
|
|
|
|
uint32_t aBufferSize) {
|
2018-05-30 22:15:35 +03:00
|
|
|
|
nsCOMPtr<nsIOutputStream> outputStream = std::move(aOutputStream);
|
2017-10-24 15:38:23 +03:00
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIBufferedOutputStream> out =
|
|
|
|
|
do_CreateInstance(NS_BUFFEREDOUTPUTSTREAM_CONTRACTID, &rv);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2017-10-24 15:38:23 +03:00
|
|
|
|
rv = out->Init(outputStream, aBufferSize);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2017-10-24 15:38:23 +03:00
|
|
|
|
out.forget(aResult);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-18 09:37:32 +03:00
|
|
|
|
[[nodiscard]] nsresult NS_NewBufferedInputStream(
|
2017-10-19 12:39:30 +03:00
|
|
|
|
nsIInputStream** aResult, already_AddRefed<nsIInputStream> aInputStream,
|
|
|
|
|
uint32_t aBufferSize) {
|
2018-05-30 22:15:35 +03:00
|
|
|
|
nsCOMPtr<nsIInputStream> inputStream = std::move(aInputStream);
|
2017-10-19 12:39:30 +03:00
|
|
|
|
|
2019-12-03 16:45:19 +03:00
|
|
|
|
nsCOMPtr<nsIBufferedInputStream> in;
|
|
|
|
|
nsresult rv = nsBufferedInputStream::Create(
|
|
|
|
|
nullptr, NS_GET_IID(nsIBufferedInputStream), getter_AddRefs(in));
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2017-10-19 12:39:30 +03:00
|
|
|
|
rv = in->Init(inputStream, aBufferSize);
|
2017-03-02 17:32:37 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2019-08-15 20:25:51 +03:00
|
|
|
|
*aResult = static_cast<nsBufferedInputStream*>(in.get())
|
|
|
|
|
->GetInputStream()
|
|
|
|
|
.take();
|
2017-03-02 17:32:37 +03:00
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-03-02 17:32:37 +03:00
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-17 22:30:05 +03:00
|
|
|
|
Result<nsCOMPtr<nsIInputStream>, nsresult> NS_NewBufferedInputStream(
|
|
|
|
|
already_AddRefed<nsIInputStream> aInputStream, uint32_t aBufferSize) {
|
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
|
|
|
|
const nsresult rv = NS_NewBufferedInputStream(
|
|
|
|
|
getter_AddRefs(stream), std::move(aInputStream), aBufferSize);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
return stream;
|
|
|
|
|
}
|
|
|
|
|
return Err(rv);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
namespace {
|
|
|
|
|
|
2018-06-18 03:30:58 +03:00
|
|
|
|
#define BUFFER_SIZE 8192
|
2017-11-09 13:18:08 +03:00
|
|
|
|
|
2018-06-19 02:41:29 +03:00
|
|
|
|
class BufferWriter final : public nsIInputStreamCallback {
|
2017-11-09 13:18:08 +03:00
|
|
|
|
public:
|
2018-06-19 02:41:29 +03:00
|
|
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
BufferWriter(nsIInputStream* aInputStream, void* aBuffer, int64_t aCount)
|
2018-06-19 02:41:29 +03:00
|
|
|
|
: mMonitor("BufferWriter.mMonitor"),
|
2017-11-09 13:18:08 +03:00
|
|
|
|
mInputStream(aInputStream),
|
|
|
|
|
mBuffer(aBuffer),
|
|
|
|
|
mCount(aCount),
|
|
|
|
|
mWrittenData(0),
|
2017-11-20 17:18:26 +03:00
|
|
|
|
mBufferType(aBuffer ? eExternal : eInternal),
|
2017-11-09 13:18:08 +03:00
|
|
|
|
mBufferSize(0) {
|
|
|
|
|
MOZ_ASSERT(aInputStream);
|
|
|
|
|
MOZ_ASSERT(aCount == -1 || aCount > 0);
|
|
|
|
|
MOZ_ASSERT_IF(mBuffer, aCount > 0);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
nsresult Write() {
|
2018-06-19 02:41:29 +03:00
|
|
|
|
NS_ASSERT_OWNINGTHREAD(BufferWriter);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
// Let's make the inputStream buffered if it's not.
|
|
|
|
|
if (!NS_InputStreamIsBuffered(mInputStream)) {
|
|
|
|
|
nsCOMPtr<nsIInputStream> bufferedStream;
|
2018-02-12 20:49:36 +03:00
|
|
|
|
nsresult rv = NS_NewBufferedInputStream(
|
2017-11-09 13:18:08 +03:00
|
|
|
|
getter_AddRefs(bufferedStream), mInputStream.forget(), BUFFER_SIZE);
|
2015-10-01 21:36:19 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
mInputStream = bufferedStream;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-19 02:41:29 +03:00
|
|
|
|
mAsyncInputStream = do_QueryInterface(mInputStream);
|
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
if (!mAsyncInputStream) {
|
|
|
|
|
return WriteSync();
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-11-09 13:18:08 +03:00
|
|
|
|
|
|
|
|
|
// Let's use mAsyncInputStream only.
|
|
|
|
|
mInputStream = nullptr;
|
|
|
|
|
|
|
|
|
|
return WriteAsync();
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-11-09 13:18:08 +03:00
|
|
|
|
|
|
|
|
|
uint64_t WrittenData() const {
|
|
|
|
|
NS_ASSERT_OWNINGTHREAD(BufferWriter);
|
|
|
|
|
return mWrittenData;
|
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
void* StealBuffer() {
|
2018-06-19 02:41:29 +03:00
|
|
|
|
NS_ASSERT_OWNINGTHREAD(BufferWriter);
|
2017-11-09 13:18:08 +03:00
|
|
|
|
MOZ_ASSERT(mBufferType == eInternal);
|
|
|
|
|
|
|
|
|
|
void* buffer = mBuffer;
|
|
|
|
|
|
|
|
|
|
mBuffer = nullptr;
|
2017-11-20 17:18:26 +03:00
|
|
|
|
mBufferSize = 0;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
return buffer;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2017-11-09 13:18:08 +03:00
|
|
|
|
~BufferWriter() {
|
|
|
|
|
if (mBuffer && mBufferType == eInternal) {
|
|
|
|
|
free(mBuffer);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
if (mTaskQueue) {
|
|
|
|
|
mTaskQueue->BeginShutdown();
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
nsresult WriteSync() {
|
|
|
|
|
NS_ASSERT_OWNINGTHREAD(BufferWriter);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
uint64_t length = (uint64_t)mCount;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
if (mCount == -1) {
|
|
|
|
|
nsresult rv = mInputStream->Available(&length);
|
2015-10-01 21:36:19 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
if (length == 0) {
|
|
|
|
|
// nothing to read.
|
|
|
|
|
return NS_OK;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-11-09 13:18:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-19 02:41:29 +03:00
|
|
|
|
if (mBufferType == eInternal) {
|
|
|
|
|
mBuffer = malloc(length);
|
|
|
|
|
if (NS_WARN_IF(!mBuffer)) {
|
2017-11-09 13:18:08 +03:00
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-11-09 13:18:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t writtenData;
|
2018-06-19 02:41:29 +03:00
|
|
|
|
nsresult rv = mInputStream->ReadSegments(NS_CopySegmentToBuffer, mBuffer,
|
|
|
|
|
length, &writtenData);
|
2017-11-09 13:18:08 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
mWrittenData = writtenData;
|
|
|
|
|
return NS_OK;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-11-20 17:18:26 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
nsresult WriteAsync() {
|
|
|
|
|
NS_ASSERT_OWNINGTHREAD(BufferWriter);
|
|
|
|
|
|
|
|
|
|
if (mCount > 0 && mBufferType == eInternal) {
|
|
|
|
|
mBuffer = malloc(mCount);
|
|
|
|
|
if (NS_WARN_IF(!mBuffer)) {
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-11-09 13:18:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
if (mCount == -1 && !MaybeExpandBufferSize()) {
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-19 02:41:29 +03:00
|
|
|
|
uint64_t offset = mWrittenData;
|
|
|
|
|
uint64_t length = mCount == -1 ? BUFFER_SIZE : mCount;
|
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
// Let's try to read data directly.
|
|
|
|
|
uint32_t writtenData;
|
|
|
|
|
nsresult rv = mAsyncInputStream->ReadSegments(
|
|
|
|
|
NS_CopySegmentToBuffer, static_cast<char*>(mBuffer) + offset, length,
|
|
|
|
|
&writtenData);
|
|
|
|
|
|
|
|
|
|
// Operation completed. Nothing more to read.
|
|
|
|
|
if (NS_SUCCEEDED(rv) && writtenData == 0) {
|
|
|
|
|
return NS_OK;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-11-09 13:18:08 +03:00
|
|
|
|
|
|
|
|
|
// If we succeeded, let's try to read again.
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
mWrittenData += writtenData;
|
2018-06-18 03:30:58 +03:00
|
|
|
|
if (mCount != -1) {
|
|
|
|
|
MOZ_ASSERT(mCount >= writtenData);
|
|
|
|
|
mCount -= writtenData;
|
2017-11-09 13:18:08 +03:00
|
|
|
|
|
|
|
|
|
// Is this the end of the reading?
|
|
|
|
|
if (mCount == 0) {
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
continue;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-11-09 13:18:08 +03:00
|
|
|
|
|
|
|
|
|
// Async wait...
|
2018-06-18 03:30:58 +03:00
|
|
|
|
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
2017-11-09 13:18:08 +03:00
|
|
|
|
rv = MaybeCreateTaskQueue();
|
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-19 02:41:29 +03:00
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
rv = mAsyncInputStream->AsyncWait(this, 0, length, mTaskQueue);
|
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-18 03:30:58 +03:00
|
|
|
|
lock.Wait();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2017-11-09 13:18:08 +03:00
|
|
|
|
|
2018-06-18 03:30:58 +03:00
|
|
|
|
// Otherwise, let's propagate the error.
|
|
|
|
|
return rv;
|
2017-11-09 13:18:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-19 02:41:29 +03:00
|
|
|
|
MOZ_ASSERT_UNREACHABLE("We should not be here");
|
|
|
|
|
return NS_ERROR_FAILURE;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2018-06-19 02:41:29 +03:00
|
|
|
|
|
|
|
|
|
nsresult MaybeCreateTaskQueue() {
|
|
|
|
|
NS_ASSERT_OWNINGTHREAD(BufferWriter);
|
|
|
|
|
|
|
|
|
|
if (!mTaskQueue) {
|
|
|
|
|
nsCOMPtr<nsIEventTarget> target =
|
|
|
|
|
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
|
|
|
|
if (!target) {
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mTaskQueue = new TaskQueue(target.forget());
|
2017-11-09 13:18:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-19 02:41:29 +03:00
|
|
|
|
return NS_OK;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-11-09 13:18:08 +03:00
|
|
|
|
|
2018-06-19 02:41:29 +03:00
|
|
|
|
NS_IMETHOD
|
|
|
|
|
OnInputStreamReady(nsIAsyncInputStream* aStream) override {
|
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
2017-11-09 13:18:08 +03:00
|
|
|
|
|
2018-06-19 02:41:29 +03:00
|
|
|
|
// We have something to read. Let's unlock the main-thread.
|
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
|
lock.Notify();
|
|
|
|
|
return NS_OK;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2018-06-19 02:41:29 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
bool MaybeExpandBufferSize() {
|
|
|
|
|
NS_ASSERT_OWNINGTHREAD(BufferWriter);
|
|
|
|
|
|
|
|
|
|
MOZ_ASSERT(mCount == -1);
|
|
|
|
|
|
|
|
|
|
if (mBufferSize >= mWrittenData + BUFFER_SIZE) {
|
|
|
|
|
// The buffer is big enough.
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CheckedUint32 bufferSize =
|
|
|
|
|
std::max<uint32_t>(static_cast<uint32_t>(mWrittenData), BUFFER_SIZE);
|
|
|
|
|
while (bufferSize.isValid() &&
|
|
|
|
|
bufferSize.value() < mWrittenData + BUFFER_SIZE) {
|
|
|
|
|
bufferSize *= 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!bufferSize.isValid()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void* buffer = realloc(mBuffer, bufferSize.value());
|
|
|
|
|
if (!buffer) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mBuffer = buffer;
|
|
|
|
|
mBufferSize = bufferSize.value();
|
|
|
|
|
return true;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-19 02:41:29 +03:00
|
|
|
|
// All the members of this class are touched on the owning thread only. The
|
|
|
|
|
// monitor is only used to communicate when there is more data to read.
|
2017-11-09 13:18:08 +03:00
|
|
|
|
Monitor mMonitor;
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> mInputStream;
|
|
|
|
|
nsCOMPtr<nsIAsyncInputStream> mAsyncInputStream;
|
|
|
|
|
|
|
|
|
|
RefPtr<TaskQueue> mTaskQueue;
|
|
|
|
|
|
|
|
|
|
void* mBuffer;
|
|
|
|
|
int64_t mCount;
|
|
|
|
|
uint64_t mWrittenData;
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
// The buffer is allocated internally and this object must release it
|
|
|
|
|
// in the DTOR if not stolen. The buffer can be reallocated.
|
|
|
|
|
eInternal,
|
|
|
|
|
|
|
|
|
|
// The buffer is not owned by this object and it cannot be reallocated.
|
|
|
|
|
eExternal,
|
|
|
|
|
} mBufferType;
|
|
|
|
|
|
|
|
|
|
// The following set if needed for the async read.
|
|
|
|
|
uint64_t mBufferSize;
|
|
|
|
|
};
|
|
|
|
|
|
2018-06-19 02:41:29 +03:00
|
|
|
|
NS_IMPL_ISUPPORTS(BufferWriter, nsIInputStreamCallback)
|
2017-11-09 13:18:08 +03:00
|
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
|
|
nsresult NS_ReadInputStreamToBuffer(nsIInputStream* aInputStream, void** aDest,
|
|
|
|
|
int64_t aCount, uint64_t* aWritten) {
|
|
|
|
|
MOZ_ASSERT(aInputStream);
|
|
|
|
|
MOZ_ASSERT(aCount >= -1);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
uint64_t dummyWritten;
|
|
|
|
|
if (!aWritten) {
|
|
|
|
|
aWritten = &dummyWritten;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
if (aCount == 0) {
|
|
|
|
|
*aWritten = 0;
|
|
|
|
|
return NS_OK;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
2017-11-09 13:18:08 +03:00
|
|
|
|
|
|
|
|
|
// This will take care of allocating and reallocating aDest.
|
|
|
|
|
RefPtr<BufferWriter> writer = new BufferWriter(aInputStream, *aDest, aCount);
|
|
|
|
|
|
|
|
|
|
nsresult rv = writer->Write();
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
*aWritten = writer->WrittenData();
|
|
|
|
|
|
|
|
|
|
if (!*aDest) {
|
|
|
|
|
*aDest = writer->StealBuffer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
nsresult NS_ReadInputStreamToString(nsIInputStream* aInputStream,
|
|
|
|
|
nsACString& aDest, int64_t aCount,
|
|
|
|
|
uint64_t* aWritten) {
|
|
|
|
|
uint64_t dummyWritten;
|
2018-02-12 19:40:17 +03:00
|
|
|
|
if (!aWritten) {
|
|
|
|
|
aWritten = &dummyWritten;
|
|
|
|
|
}
|
2018-02-12 20:49:36 +03:00
|
|
|
|
|
|
|
|
|
// Nothing to do if aCount is 0.
|
|
|
|
|
if (aCount == 0) {
|
|
|
|
|
aDest.Truncate();
|
|
|
|
|
*aWritten = 0;
|
2018-06-18 03:30:58 +03:00
|
|
|
|
return NS_OK;
|
2018-02-12 20:49:36 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-12 19:40:17 +03:00
|
|
|
|
// If we have the size, we can pre-allocate the buffer.
|
|
|
|
|
if (aCount > 0) {
|
|
|
|
|
if (NS_WARN_IF(aCount >= INT32_MAX) ||
|
|
|
|
|
NS_WARN_IF(!aDest.SetLength(aCount, mozilla::fallible))) {
|
2018-02-12 20:49:36 +03:00
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2018-02-12 19:40:17 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
void* dest = aDest.BeginWriting();
|
|
|
|
|
nsresult rv =
|
|
|
|
|
NS_ReadInputStreamToBuffer(aInputStream, &dest, aCount, aWritten);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
if ((uint64_t)aCount > *aWritten) {
|
|
|
|
|
aDest.Truncate(*aWritten);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-12 19:40:17 +03:00
|
|
|
|
// If the size is unknown, BufferWriter will allocate the buffer.
|
2017-11-09 13:18:08 +03:00
|
|
|
|
void* dest = nullptr;
|
|
|
|
|
nsresult rv =
|
2018-02-12 20:49:36 +03:00
|
|
|
|
NS_ReadInputStreamToBuffer(aInputStream, &dest, aCount, aWritten);
|
2017-11-09 13:18:08 +03:00
|
|
|
|
MOZ_ASSERT_IF(NS_FAILED(rv), dest == nullptr);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
if (!dest) {
|
2018-06-18 03:30:58 +03:00
|
|
|
|
MOZ_ASSERT(*aWritten == 0);
|
2018-02-12 19:40:17 +03:00
|
|
|
|
aDest.Truncate();
|
2018-06-18 03:30:58 +03:00
|
|
|
|
return NS_OK;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 13:18:08 +03:00
|
|
|
|
aDest.Adopt(reinterpret_cast<char*>(dest), *aWritten);
|
2018-06-18 03:30:58 +03:00
|
|
|
|
return NS_OK;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-15 16:39:51 +03:00
|
|
|
|
nsresult NS_NewURI(nsIURI** result, const nsACString& spec,
|
|
|
|
|
NotNull<const Encoding*> encoding,
|
|
|
|
|
nsIURI* baseURI /* = nullptr */) {
|
2017-06-18 14:37:50 +03:00
|
|
|
|
nsAutoCString charset;
|
|
|
|
|
encoding->Name(charset);
|
2019-07-15 16:39:51 +03:00
|
|
|
|
return NS_NewURI(result, spec, charset.get(), baseURI);
|
2017-06-18 14:37:50 +03:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-15 16:39:51 +03:00
|
|
|
|
nsresult NS_NewURI(nsIURI** result, const nsAString& aSpec,
|
|
|
|
|
const char* charset /* = nullptr */,
|
|
|
|
|
nsIURI* baseURI /* = nullptr */) {
|
2019-03-07 20:23:35 +03:00
|
|
|
|
nsAutoCString spec;
|
|
|
|
|
if (!AppendUTF16toUTF8(aSpec, spec, mozilla::fallible)) {
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
2019-07-15 16:39:51 +03:00
|
|
|
|
return NS_NewURI(result, spec, charset, baseURI);
|
2017-03-02 17:32:37 +03:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-15 16:39:51 +03:00
|
|
|
|
nsresult NS_NewURI(nsIURI** result, const nsAString& aSpec,
|
|
|
|
|
NotNull<const Encoding*> encoding,
|
|
|
|
|
nsIURI* baseURI /* = nullptr */) {
|
2019-03-07 20:23:35 +03:00
|
|
|
|
nsAutoCString spec;
|
|
|
|
|
if (!AppendUTF16toUTF8(aSpec, spec, mozilla::fallible)) {
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
2019-07-15 16:39:51 +03:00
|
|
|
|
return NS_NewURI(result, spec, encoding, baseURI);
|
2017-06-18 14:37:50 +03:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-15 16:39:51 +03:00
|
|
|
|
nsresult NS_NewURI(nsIURI** result, const char* spec,
|
|
|
|
|
nsIURI* baseURI /* = nullptr */) {
|
|
|
|
|
return NS_NewURI(result, nsDependentCString(spec), nullptr, baseURI);
|
2017-03-02 17:32:37 +03:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-19 18:11:31 +03:00
|
|
|
|
static nsresult NewStandardURI(const nsACString& aSpec, const char* aCharset,
|
|
|
|
|
nsIURI* aBaseURI, int32_t aDefaultPort,
|
|
|
|
|
nsIURI** aURI) {
|
|
|
|
|
return NS_MutateURI(new nsStandardURL::Mutator())
|
2021-08-12 10:40:58 +03:00
|
|
|
|
.Apply(&nsIStandardURLMutator::Init, nsIStandardURL::URLTYPE_AUTHORITY,
|
2021-08-12 10:40:58 +03:00
|
|
|
|
aDefaultPort, aSpec, aCharset, aBaseURI, nullptr)
|
2019-03-19 18:11:31 +03:00
|
|
|
|
.Finalize(aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-20 21:54:03 +03:00
|
|
|
|
nsresult NS_GetSpecWithNSURLEncoding(nsACString& aResult,
|
|
|
|
|
const nsACString& aSpec) {
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
|
nsresult rv = NS_NewURIWithNSURLEncoding(getter_AddRefs(uri), aSpec);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
return uri->GetAsciiSpec(aResult);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewURIWithNSURLEncoding(nsIURI** aResult, const nsACString& aSpec) {
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
|
nsresult rv = NS_NewURI(getter_AddRefs(uri), aSpec);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
// Escape the ref portion of the URL. An unescaped '#' to indicate
|
|
|
|
|
// the beginning of the ref component is accepted by NSURL, but '#'
|
|
|
|
|
// characters in the ref must be escaped. The ref returned from
|
|
|
|
|
// GetRef() does not include the leading '#'.
|
|
|
|
|
nsAutoCString ref, escapedRef;
|
|
|
|
|
if (NS_SUCCEEDED(uri->GetRef(ref)) && !ref.IsEmpty()) {
|
|
|
|
|
if (!NS_Escape(ref, escapedRef, url_AppleExtra)) {
|
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
}
|
|
|
|
|
rv = NS_MutateURI(uri).SetRef(escapedRef).Finalize(uri);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Escape the file path
|
|
|
|
|
nsAutoCString filePath, escapedFilePath;
|
|
|
|
|
if (NS_SUCCEEDED(uri->GetFilePath(filePath)) && !filePath.IsEmpty()) {
|
|
|
|
|
if (!NS_Escape(filePath, escapedFilePath, url_AppleExtra)) {
|
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
}
|
|
|
|
|
rv = NS_MutateURI(uri).SetFilePath(escapedFilePath).Finalize(uri);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Escape the query
|
|
|
|
|
nsAutoCString query, escapedQuery;
|
|
|
|
|
if (NS_SUCCEEDED(uri->GetQuery(query)) && !query.IsEmpty()) {
|
|
|
|
|
if (!NS_Escape(query, escapedQuery, url_AppleExtra)) {
|
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
}
|
|
|
|
|
rv = NS_MutateURI(uri).SetQuery(escapedQuery).Finalize(uri);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uri.forget(aResult);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-19 18:11:31 +03:00
|
|
|
|
extern MOZ_THREAD_LOCAL(uint32_t) gTlsURLRecursionCount;
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
class TlsAutoIncrement {
|
|
|
|
|
public:
|
|
|
|
|
explicit TlsAutoIncrement(T& var) : mVar(var) {
|
|
|
|
|
mValue = mVar.get();
|
|
|
|
|
mVar.set(mValue + 1);
|
|
|
|
|
}
|
|
|
|
|
~TlsAutoIncrement() {
|
|
|
|
|
typename T::Type value = mVar.get();
|
|
|
|
|
MOZ_ASSERT(value == mValue + 1);
|
|
|
|
|
mVar.set(value - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typename T::Type value() { return mValue; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typename T::Type mValue;
|
|
|
|
|
T& mVar;
|
|
|
|
|
};
|
|
|
|
|
|
2019-05-28 17:17:04 +03:00
|
|
|
|
nsresult NS_NewURI(nsIURI** aURI, const nsACString& aSpec,
|
|
|
|
|
const char* aCharset /* = nullptr */,
|
2019-07-15 16:39:51 +03:00
|
|
|
|
nsIURI* aBaseURI /* = nullptr */) {
|
2019-03-19 18:11:31 +03:00
|
|
|
|
TlsAutoIncrement<decltype(gTlsURLRecursionCount)> inc(gTlsURLRecursionCount);
|
|
|
|
|
if (inc.value() >= MAX_RECURSION_COUNT) {
|
|
|
|
|
return NS_ERROR_MALFORMED_URI;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-12 19:57:54 +03:00
|
|
|
|
nsCOMPtr<nsIIOService> ioService = do_GetIOService();
|
|
|
|
|
if (!ioService) {
|
|
|
|
|
// Individual protocol handlers unfortunately rely on the ioservice, let's
|
|
|
|
|
// return an error here instead of causing unpredictable crashes later.
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-11 15:38:29 +03:00
|
|
|
|
if (StaticPrefs::network_url_max_length() &&
|
|
|
|
|
aSpec.Length() > StaticPrefs::network_url_max_length()) {
|
|
|
|
|
return NS_ERROR_MALFORMED_URI;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-19 18:11:31 +03:00
|
|
|
|
nsAutoCString scheme;
|
|
|
|
|
nsresult rv = net_ExtractURLScheme(aSpec, scheme);
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
// then aSpec is relative
|
|
|
|
|
if (!aBaseURI) {
|
|
|
|
|
return NS_ERROR_MALFORMED_URI;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!aSpec.IsEmpty() && aSpec[0] == '#') {
|
|
|
|
|
// Looks like a reference instead of a fully-specified URI.
|
|
|
|
|
// --> initialize |uri| as a clone of |aBaseURI|, with ref appended.
|
|
|
|
|
return NS_GetURIWithNewRef(aBaseURI, aSpec, aURI);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rv = aBaseURI->GetScheme(scheme);
|
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("ws")) {
|
|
|
|
|
return NewStandardURI(aSpec, aCharset, aBaseURI, NS_HTTP_DEFAULT_PORT,
|
|
|
|
|
aURI);
|
|
|
|
|
}
|
|
|
|
|
if (scheme.EqualsLiteral("https") || scheme.EqualsLiteral("wss")) {
|
|
|
|
|
return NewStandardURI(aSpec, aCharset, aBaseURI, NS_HTTPS_DEFAULT_PORT,
|
|
|
|
|
aURI);
|
|
|
|
|
}
|
|
|
|
|
if (scheme.EqualsLiteral("ftp")) {
|
|
|
|
|
return NewStandardURI(aSpec, aCharset, aBaseURI, 21, aURI);
|
|
|
|
|
}
|
2019-05-28 16:50:43 +03:00
|
|
|
|
if (scheme.EqualsLiteral("ssh")) {
|
|
|
|
|
return NewStandardURI(aSpec, aCharset, aBaseURI, 22, aURI);
|
|
|
|
|
}
|
2019-03-19 18:11:31 +03:00
|
|
|
|
|
|
|
|
|
if (scheme.EqualsLiteral("file")) {
|
|
|
|
|
nsAutoCString buf(aSpec);
|
|
|
|
|
#if defined(XP_WIN)
|
|
|
|
|
buf.Truncate();
|
|
|
|
|
if (!net_NormalizeFileURL(aSpec, buf)) {
|
|
|
|
|
buf = aSpec;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return NS_MutateURI(new nsStandardURL::Mutator())
|
2021-08-12 10:40:58 +03:00
|
|
|
|
.Apply(&nsIFileURLMutator::MarkFileURL)
|
|
|
|
|
.Apply(&nsIStandardURLMutator::Init,
|
2021-08-12 10:40:58 +03:00
|
|
|
|
nsIStandardURL::URLTYPE_NO_AUTHORITY, -1, buf, aCharset,
|
|
|
|
|
aBaseURI, nullptr)
|
2019-03-19 18:11:31 +03:00
|
|
|
|
.Finalize(aURI);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (scheme.EqualsLiteral("data")) {
|
|
|
|
|
return nsDataHandler::CreateNewURI(aSpec, aCharset, aBaseURI, aURI);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (scheme.EqualsLiteral("moz-safe-about") ||
|
|
|
|
|
scheme.EqualsLiteral("page-icon") || scheme.EqualsLiteral("moz") ||
|
|
|
|
|
scheme.EqualsLiteral("moz-anno") ||
|
|
|
|
|
scheme.EqualsLiteral("moz-fonttable")) {
|
|
|
|
|
return NS_MutateURI(new nsSimpleURI::Mutator())
|
|
|
|
|
.SetSpec(aSpec)
|
|
|
|
|
.Finalize(aURI);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (scheme.EqualsLiteral("chrome")) {
|
|
|
|
|
return nsChromeProtocolHandler::CreateNewURI(aSpec, aCharset, aBaseURI,
|
|
|
|
|
aURI);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (scheme.EqualsLiteral("javascript")) {
|
|
|
|
|
return nsJSProtocolHandler::CreateNewURI(aSpec, aCharset, aBaseURI, aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-19 18:13:47 +03:00
|
|
|
|
if (scheme.EqualsLiteral("blob")) {
|
|
|
|
|
return BlobURLProtocolHandler::CreateNewURI(aSpec, aCharset, aBaseURI,
|
|
|
|
|
aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 16:48:49 +03:00
|
|
|
|
if (scheme.EqualsLiteral("view-source")) {
|
|
|
|
|
return nsViewSourceHandler::CreateNewURI(aSpec, aCharset, aBaseURI, aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 16:48:56 +03:00
|
|
|
|
if (scheme.EqualsLiteral("resource")) {
|
2019-05-28 16:49:05 +03:00
|
|
|
|
RefPtr<nsResProtocolHandler> handler = nsResProtocolHandler::GetSingleton();
|
2019-05-28 16:48:56 +03:00
|
|
|
|
if (!handler) {
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
}
|
|
|
|
|
return handler->NewURI(aSpec, aCharset, aBaseURI, aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 16:49:45 +03:00
|
|
|
|
if (scheme.EqualsLiteral("indexeddb")) {
|
|
|
|
|
return NS_MutateURI(new nsStandardURL::Mutator())
|
2021-08-12 10:40:58 +03:00
|
|
|
|
.Apply(&nsIStandardURLMutator::Init, nsIStandardURL::URLTYPE_AUTHORITY,
|
2021-08-12 10:40:58 +03:00
|
|
|
|
0, aSpec, aCharset, aBaseURI, nullptr)
|
2019-05-28 16:49:45 +03:00
|
|
|
|
.Finalize(aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 16:48:56 +03:00
|
|
|
|
if (scheme.EqualsLiteral("moz-extension")) {
|
2019-05-28 16:49:05 +03:00
|
|
|
|
RefPtr<mozilla::net::ExtensionProtocolHandler> handler =
|
|
|
|
|
mozilla::net::ExtensionProtocolHandler::GetSingleton();
|
2019-05-28 16:48:56 +03:00
|
|
|
|
if (!handler) {
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
}
|
|
|
|
|
return handler->NewURI(aSpec, aCharset, aBaseURI, aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-06 20:46:52 +03:00
|
|
|
|
if (scheme.EqualsLiteral("moz-page-thumb")) {
|
|
|
|
|
// The moz-page-thumb service runs JS to resolve a URI to a
|
|
|
|
|
// storage location, so this should only ever run on the main
|
|
|
|
|
// thread.
|
|
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RefPtr<mozilla::net::PageThumbProtocolHandler> handler =
|
|
|
|
|
mozilla::net::PageThumbProtocolHandler::GetSingleton();
|
|
|
|
|
if (!handler) {
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
}
|
|
|
|
|
return handler->NewURI(aSpec, aCharset, aBaseURI, aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 16:49:17 +03:00
|
|
|
|
if (scheme.EqualsLiteral("about")) {
|
|
|
|
|
return nsAboutProtocolHandler::CreateNewURI(aSpec, aCharset, aBaseURI,
|
|
|
|
|
aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 16:49:07 +03:00
|
|
|
|
if (scheme.EqualsLiteral("jar")) {
|
|
|
|
|
return NS_MutateURI(new nsJARURI::Mutator())
|
2021-08-12 10:40:58 +03:00
|
|
|
|
.Apply(&nsIJARURIMutator::SetSpecBaseCharset, aSpec, aBaseURI, aCharset)
|
2019-05-28 16:49:07 +03:00
|
|
|
|
.Finalize(aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 16:49:19 +03:00
|
|
|
|
if (scheme.EqualsLiteral("moz-icon")) {
|
|
|
|
|
return NS_MutateURI(new nsMozIconURI::Mutator())
|
|
|
|
|
.SetSpec(aSpec)
|
|
|
|
|
.Finalize(aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 16:47:18 +03:00
|
|
|
|
#ifdef MOZ_WIDGET_GTK
|
|
|
|
|
if (scheme.EqualsLiteral("smb") || scheme.EqualsLiteral("sftp")) {
|
|
|
|
|
return NS_MutateURI(new nsStandardURL::Mutator())
|
2021-08-12 10:40:58 +03:00
|
|
|
|
.Apply(&nsIStandardURLMutator::Init, nsIStandardURL::URLTYPE_STANDARD,
|
2021-08-12 10:40:58 +03:00
|
|
|
|
-1, aSpec, aCharset, aBaseURI, nullptr)
|
2019-05-28 16:47:18 +03:00
|
|
|
|
.Finalize(aURI);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-05-28 16:49:45 +03:00
|
|
|
|
if (scheme.EqualsLiteral("android")) {
|
|
|
|
|
return NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
|
2021-08-12 10:40:58 +03:00
|
|
|
|
.Apply(&nsIStandardURLMutator::Init, nsIStandardURL::URLTYPE_STANDARD,
|
2021-08-12 10:40:58 +03:00
|
|
|
|
-1, aSpec, aCharset, aBaseURI, nullptr)
|
2019-05-28 16:49:45 +03:00
|
|
|
|
.Finalize(aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-31 22:52:30 +03:00
|
|
|
|
// web-extensions can add custom protocol implementations with standard URLs
|
|
|
|
|
// that have notion of hostname, authority and relative URLs. Below we
|
|
|
|
|
// manually check agains set of known protocols schemes until more general
|
|
|
|
|
// solution is in place (See Bug 1569733)
|
2019-12-11 23:17:53 +03:00
|
|
|
|
if (!StaticPrefs::network_url_useDefaultURI()) {
|
|
|
|
|
if (scheme.EqualsLiteral("dweb") || scheme.EqualsLiteral("dat") ||
|
|
|
|
|
scheme.EqualsLiteral("ipfs") || scheme.EqualsLiteral("ipns") ||
|
|
|
|
|
scheme.EqualsLiteral("ssb") || scheme.EqualsLiteral("wtp")) {
|
|
|
|
|
return NewStandardURI(aSpec, aCharset, aBaseURI, -1, aURI);
|
|
|
|
|
}
|
2019-06-28 16:12:49 +03:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-31 12:53:59 +03:00
|
|
|
|
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
|
2019-07-15 16:39:51 +03:00
|
|
|
|
rv = NS_NewMailnewsURI(aURI, aSpec, aCharset, aBaseURI);
|
2019-05-31 12:53:59 +03:00
|
|
|
|
if (rv != NS_ERROR_UNKNOWN_PROTOCOL) {
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-05-28 16:50:00 +03:00
|
|
|
|
if (aBaseURI) {
|
|
|
|
|
nsAutoCString newSpec;
|
|
|
|
|
rv = aBaseURI->Resolve(aSpec, newSpec);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
nsAutoCString newScheme;
|
|
|
|
|
rv = net_ExtractURLScheme(newSpec, newScheme);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
// The scheme shouldn't really change at this point.
|
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(newScheme == scheme);
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-11 23:17:53 +03:00
|
|
|
|
if (StaticPrefs::network_url_useDefaultURI()) {
|
|
|
|
|
return NS_MutateURI(new DefaultURI::Mutator())
|
|
|
|
|
.SetSpec(newSpec)
|
|
|
|
|
.Finalize(aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 16:50:00 +03:00
|
|
|
|
return NS_MutateURI(new nsSimpleURI::Mutator())
|
|
|
|
|
.SetSpec(newSpec)
|
|
|
|
|
.Finalize(aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-11 23:17:53 +03:00
|
|
|
|
if (StaticPrefs::network_url_useDefaultURI()) {
|
|
|
|
|
return NS_MutateURI(new DefaultURI::Mutator())
|
|
|
|
|
.SetSpec(aSpec)
|
|
|
|
|
.Finalize(aURI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 16:48:49 +03:00
|
|
|
|
// Falls back to external protocol handler.
|
|
|
|
|
return NS_MutateURI(new nsSimpleURI::Mutator()).SetSpec(aSpec).Finalize(aURI);
|
2019-03-19 18:11:31 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-07 16:56:30 +03:00
|
|
|
|
nsresult NS_GetSanitizedURIStringFromURI(nsIURI* aUri,
|
|
|
|
|
nsAString& aSanitizedSpec) {
|
|
|
|
|
aSanitizedSpec.Truncate();
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri = do_QueryInterface(aUri);
|
|
|
|
|
nsAutoCString cSpec;
|
|
|
|
|
nsresult rv;
|
|
|
|
|
if (safeUri) {
|
|
|
|
|
rv = safeUri->GetSensitiveInfoHiddenSpec(cSpec);
|
|
|
|
|
} else {
|
|
|
|
|
rv = aUri->GetSpec(cSpec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
aSanitizedSpec.Assign(NS_ConvertUTF8toUTF16(cSpec));
|
|
|
|
|
}
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-09 05:54:38 +03:00
|
|
|
|
nsresult NS_LoadPersistentPropertiesFromURISpec(
|
|
|
|
|
nsIPersistentProperties** outResult, const nsACString& aSpec) {
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
|
nsresult rv = NS_NewURI(getter_AddRefs(uri), aSpec);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsCOMPtr<nsIChannel> channel;
|
2015-11-09 05:54:38 +03:00
|
|
|
|
rv = NS_NewChannel(getter_AddRefs(channel), uri,
|
|
|
|
|
nsContentUtils::GetSystemPrincipal(),
|
2020-07-15 14:20:45 +03:00
|
|
|
|
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
|
2015-11-09 05:54:38 +03:00
|
|
|
|
nsIContentPolicy::TYPE_OTHER);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
nsCOMPtr<nsIInputStream> in;
|
2019-02-12 19:08:25 +03:00
|
|
|
|
rv = channel->Open(getter_AddRefs(in));
|
2015-05-20 05:48:00 +03:00
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
2018-09-15 19:58:31 +03:00
|
|
|
|
nsCOMPtr<nsIPersistentProperties> properties = new nsPersistentProperties();
|
2015-05-20 05:48:00 +03:00
|
|
|
|
rv = properties->Load(in);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
properties.swap(*outResult);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NS_UsePrivateBrowsing(nsIChannel* channel) {
|
2017-05-03 05:08:14 +03:00
|
|
|
|
OriginAttributes attrs;
|
2020-05-05 23:56:04 +03:00
|
|
|
|
bool result = StoragePrincipalHelper::GetOriginAttributes(
|
|
|
|
|
channel, attrs, StoragePrincipalHelper::eRegularPrincipal);
|
2017-05-03 05:08:14 +03:00
|
|
|
|
NS_ENSURE_TRUE(result, result);
|
|
|
|
|
return attrs.mPrivateBrowsingId > 0;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-07 02:33:15 +03:00
|
|
|
|
bool NS_HasBeenCrossOrigin(nsIChannel* aChannel, bool aReport) {
|
2019-02-20 15:27:25 +03:00
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
2017-01-03 22:59:30 +03:00
|
|
|
|
// TYPE_DOCUMENT loads have a null LoadingPrincipal and can not be cross
|
|
|
|
|
// origin.
|
2020-04-06 21:57:36 +03:00
|
|
|
|
if (!loadInfo->GetLoadingPrincipal()) {
|
2017-01-03 22:59:30 +03:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2015-12-07 02:33:15 +03:00
|
|
|
|
|
|
|
|
|
// Always treat tainted channels as cross-origin.
|
|
|
|
|
if (loadInfo->GetTainting() != LoadTainting::Basic) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-06 21:57:36 +03:00
|
|
|
|
nsCOMPtr<nsIPrincipal> loadingPrincipal = loadInfo->GetLoadingPrincipal();
|
2015-12-07 02:33:15 +03:00
|
|
|
|
uint32_t mode = loadInfo->GetSecurityMode();
|
|
|
|
|
bool dataInherits =
|
2020-07-15 14:20:45 +03:00
|
|
|
|
mode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_INHERITS_SEC_CONTEXT ||
|
|
|
|
|
mode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT ||
|
|
|
|
|
mode == nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT;
|
2015-12-07 02:33:15 +03:00
|
|
|
|
|
|
|
|
|
bool aboutBlankInherits = dataInherits && loadInfo->GetAboutBlankInherits();
|
|
|
|
|
|
2019-12-13 09:24:12 +03:00
|
|
|
|
uint64_t innerWindowID = loadInfo->GetInnerWindowID();
|
|
|
|
|
|
2017-05-25 20:42:00 +03:00
|
|
|
|
for (nsIRedirectHistoryEntry* redirectHistoryEntry :
|
|
|
|
|
loadInfo->RedirectChain()) {
|
|
|
|
|
nsCOMPtr<nsIPrincipal> principal;
|
|
|
|
|
redirectHistoryEntry->GetPrincipal(getter_AddRefs(principal));
|
|
|
|
|
if (!principal) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-07 02:33:15 +03:00
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
2020-04-27 13:54:47 +03:00
|
|
|
|
auto* basePrin = BasePrincipal::Cast(principal);
|
|
|
|
|
basePrin->GetURI(getter_AddRefs(uri));
|
2015-12-07 02:33:15 +03:00
|
|
|
|
if (!uri) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aboutBlankInherits && NS_IsAboutBlank(uri)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-13 09:24:12 +03:00
|
|
|
|
nsresult res;
|
|
|
|
|
if (aReport) {
|
|
|
|
|
res = loadingPrincipal->CheckMayLoadWithReporting(uri, dataInherits,
|
|
|
|
|
innerWindowID);
|
|
|
|
|
} else {
|
|
|
|
|
res = loadingPrincipal->CheckMayLoad(uri, dataInherits);
|
|
|
|
|
}
|
|
|
|
|
if (NS_FAILED(res)) {
|
2015-12-07 02:33:15 +03:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
|
NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
|
|
|
|
if (!uri) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aboutBlankInherits && NS_IsAboutBlank(uri)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-13 09:24:12 +03:00
|
|
|
|
nsresult res;
|
|
|
|
|
if (aReport) {
|
|
|
|
|
res = loadingPrincipal->CheckMayLoadWithReporting(uri, dataInherits,
|
|
|
|
|
innerWindowID);
|
|
|
|
|
} else {
|
|
|
|
|
res = loadingPrincipal->CheckMayLoad(uri, dataInherits);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_FAILED(res);
|
2015-12-07 02:33:15 +03:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-19 20:43:52 +03:00
|
|
|
|
bool NS_IsSafeMethodNav(nsIChannel* aChannel) {
|
2018-04-08 20:52:05 +03:00
|
|
|
|
RefPtr<HttpBaseChannel> baseChan = do_QueryObject(aChannel);
|
|
|
|
|
if (!baseChan) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
nsHttpRequestHead* requestHead = baseChan->GetRequestHead();
|
|
|
|
|
if (!requestHead) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return requestHead->IsSafeMethod();
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
void NS_WrapAuthPrompt(nsIAuthPrompt* aAuthPrompt,
|
|
|
|
|
nsIAuthPrompt2** aAuthPrompt2) {
|
|
|
|
|
nsCOMPtr<nsIAuthPromptAdapterFactory> factory =
|
|
|
|
|
do_GetService(NS_AUTHPROMPT_ADAPTER_FACTORY_CONTRACTID);
|
|
|
|
|
if (!factory) return;
|
|
|
|
|
|
|
|
|
|
NS_WARNING("Using deprecated nsIAuthPrompt");
|
|
|
|
|
factory->CreateAdapter(aAuthPrompt, aAuthPrompt2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NS_QueryAuthPrompt2(nsIInterfaceRequestor* aCallbacks,
|
|
|
|
|
nsIAuthPrompt2** aAuthPrompt) {
|
|
|
|
|
CallGetInterface(aCallbacks, aAuthPrompt);
|
|
|
|
|
if (*aAuthPrompt) return;
|
|
|
|
|
|
|
|
|
|
// Maybe only nsIAuthPrompt is provided and we have to wrap it.
|
|
|
|
|
nsCOMPtr<nsIAuthPrompt> prompt(do_GetInterface(aCallbacks));
|
|
|
|
|
if (!prompt) return;
|
|
|
|
|
|
|
|
|
|
NS_WrapAuthPrompt(prompt, aAuthPrompt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NS_QueryAuthPrompt2(nsIChannel* aChannel, nsIAuthPrompt2** aAuthPrompt) {
|
|
|
|
|
*aAuthPrompt = nullptr;
|
|
|
|
|
|
|
|
|
|
// We want to use any auth prompt we can find on the channel's callbacks,
|
|
|
|
|
// and if that fails use the loadgroup's prompt (if any)
|
|
|
|
|
// Therefore, we can't just use NS_QueryNotificationCallbacks, because
|
|
|
|
|
// that would prefer a loadgroup's nsIAuthPrompt2 over a channel's
|
|
|
|
|
// nsIAuthPrompt.
|
|
|
|
|
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
|
|
|
|
aChannel->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
|
|
|
|
if (callbacks) {
|
|
|
|
|
NS_QueryAuthPrompt2(callbacks, aAuthPrompt);
|
|
|
|
|
if (*aAuthPrompt) return;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsCOMPtr<nsILoadGroup> group;
|
|
|
|
|
aChannel->GetLoadGroup(getter_AddRefs(group));
|
2018-07-23 14:28:47 +03:00
|
|
|
|
if (!group) return;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
group->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
|
|
|
|
if (!callbacks) return;
|
|
|
|
|
NS_QueryAuthPrompt2(callbacks, aAuthPrompt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewNotificationCallbacksAggregation(
|
|
|
|
|
nsIInterfaceRequestor* callbacks, nsILoadGroup* loadGroup,
|
|
|
|
|
nsIEventTarget* target, nsIInterfaceRequestor** result) {
|
|
|
|
|
nsCOMPtr<nsIInterfaceRequestor> cbs;
|
|
|
|
|
if (loadGroup) loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
|
|
|
|
|
return NS_NewInterfaceRequestorAggregation(callbacks, cbs, target, result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewNotificationCallbacksAggregation(
|
|
|
|
|
nsIInterfaceRequestor* callbacks, nsILoadGroup* loadGroup,
|
|
|
|
|
nsIInterfaceRequestor** result) {
|
|
|
|
|
return NS_NewNotificationCallbacksAggregation(callbacks, loadGroup, nullptr,
|
|
|
|
|
result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_DoImplGetInnermostURI(nsINestedURI* nestedURI, nsIURI** result) {
|
2018-04-28 22:50:58 +03:00
|
|
|
|
MOZ_ASSERT(nestedURI, "Must have a nested URI!");
|
|
|
|
|
MOZ_ASSERT(!*result, "Must have null *result");
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> inner;
|
|
|
|
|
nsresult rv = nestedURI->GetInnerURI(getter_AddRefs(inner));
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
// We may need to loop here until we reach the innermost
|
|
|
|
|
// URI.
|
|
|
|
|
nsCOMPtr<nsINestedURI> nestedInner(do_QueryInterface(inner));
|
|
|
|
|
while (nestedInner) {
|
|
|
|
|
rv = nestedInner->GetInnerURI(getter_AddRefs(inner));
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
nestedInner = do_QueryInterface(inner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Found the innermost one if we reach here.
|
|
|
|
|
inner.swap(*result);
|
|
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_ImplGetInnermostURI(nsINestedURI* nestedURI, nsIURI** result) {
|
|
|
|
|
// Make it safe to use swap()
|
|
|
|
|
*result = nullptr;
|
|
|
|
|
|
|
|
|
|
return NS_DoImplGetInnermostURI(nestedURI, result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
already_AddRefed<nsIURI> NS_GetInnermostURI(nsIURI* aURI) {
|
2018-04-28 22:50:58 +03:00
|
|
|
|
MOZ_ASSERT(aURI, "Must have URI");
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri = aURI;
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsINestedURI> nestedURI(do_QueryInterface(uri));
|
|
|
|
|
if (!nestedURI) {
|
|
|
|
|
return uri.forget();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult rv = nestedURI->GetInnermostURI(getter_AddRefs(uri));
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return uri.forget();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_GetFinalChannelURI(nsIChannel* channel, nsIURI** uri) {
|
|
|
|
|
*uri = nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2019-02-20 15:27:25 +03:00
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
|
|
|
|
nsCOMPtr<nsIURI> resultPrincipalURI;
|
|
|
|
|
loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
|
|
|
|
|
if (resultPrincipalURI) {
|
|
|
|
|
resultPrincipalURI.forget(uri);
|
|
|
|
|
return NS_OK;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2017-05-13 14:55:11 +03:00
|
|
|
|
return channel->GetOriginalURI(uri);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
nsresult NS_URIChainHasFlags(nsIURI* uri, uint32_t flags, bool* result) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
return util->URIChainHasFlags(uri, flags, result);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
uint32_t NS_SecurityHashURI(nsIURI* aURI) {
|
|
|
|
|
nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
|
|
|
|
|
|
|
|
|
|
nsAutoCString scheme;
|
|
|
|
|
uint32_t schemeHash = 0;
|
2021-06-04 15:35:16 +03:00
|
|
|
|
if (NS_SUCCEEDED(baseURI->GetScheme(scheme))) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
schemeHash = mozilla::HashString(scheme);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
// TODO figure out how to hash file:// URIs
|
|
|
|
|
if (scheme.EqualsLiteral("file")) return schemeHash; // sad face
|
|
|
|
|
|
2017-02-18 00:25:48 +03:00
|
|
|
|
#if IS_ORIGIN_IS_FULL_SPEC_DEFINED
|
2016-01-20 22:02:23 +03:00
|
|
|
|
bool hasFlag;
|
|
|
|
|
if (NS_FAILED(NS_URIChainHasFlags(
|
|
|
|
|
baseURI, nsIProtocolHandler::ORIGIN_IS_FULL_SPEC, &hasFlag)) ||
|
|
|
|
|
hasFlag) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsAutoCString spec;
|
|
|
|
|
uint32_t specHash;
|
|
|
|
|
nsresult res = baseURI->GetSpec(spec);
|
|
|
|
|
if (NS_SUCCEEDED(res))
|
|
|
|
|
specHash = mozilla::HashString(spec);
|
|
|
|
|
else
|
|
|
|
|
specHash = static_cast<uint32_t>(res);
|
|
|
|
|
return specHash;
|
|
|
|
|
}
|
2017-02-18 00:25:48 +03:00
|
|
|
|
#endif
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
nsAutoCString host;
|
|
|
|
|
uint32_t hostHash = 0;
|
2021-06-04 15:35:16 +03:00
|
|
|
|
if (NS_SUCCEEDED(baseURI->GetAsciiHost(host))) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
hostHash = mozilla::HashString(host);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
return mozilla::AddToHash(schemeHash, hostHash, NS_GetRealPort(baseURI));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NS_SecurityCompareURIs(nsIURI* aSourceURI, nsIURI* aTargetURI,
|
|
|
|
|
bool aStrictFileOriginPolicy) {
|
2018-07-31 11:27:00 +03:00
|
|
|
|
nsresult rv;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
// Note that this is not an Equals() test on purpose -- for URIs that don't
|
|
|
|
|
// support host/port, we want equality to basically be object identity, for
|
|
|
|
|
// security purposes. Otherwise, for example, two javascript: URIs that
|
|
|
|
|
// are otherwise unrelated could end up "same origin", which would be
|
|
|
|
|
// unfortunate.
|
|
|
|
|
if (aSourceURI && aSourceURI == aTargetURI) {
|
2015-12-07 02:33:15 +03:00
|
|
|
|
return true;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (!aTargetURI || !aSourceURI) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If either URI is a nested URI, get the base URI
|
|
|
|
|
nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(aSourceURI);
|
|
|
|
|
nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI);
|
|
|
|
|
|
2018-07-31 11:27:00 +03:00
|
|
|
|
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
|
|
|
|
|
// Check if either URI has a special origin.
|
|
|
|
|
nsCOMPtr<nsIURI> origin;
|
|
|
|
|
nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
|
|
|
|
|
do_QueryInterface(sourceBaseURI);
|
|
|
|
|
if (uriWithSpecialOrigin) {
|
|
|
|
|
rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
|
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
MOZ_ASSERT(origin);
|
|
|
|
|
sourceBaseURI = origin;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2018-07-31 11:27:00 +03:00
|
|
|
|
uriWithSpecialOrigin = do_QueryInterface(targetBaseURI);
|
|
|
|
|
if (uriWithSpecialOrigin) {
|
|
|
|
|
rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
|
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
MOZ_ASSERT(origin);
|
|
|
|
|
targetBaseURI = origin;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2018-07-31 11:27:00 +03:00
|
|
|
|
#endif
|
|
|
|
|
|
2018-07-24 23:15:57 +03:00
|
|
|
|
nsCOMPtr<nsIPrincipal> sourceBlobPrincipal;
|
|
|
|
|
if (BlobURLProtocolHandler::GetBlobURLPrincipal(
|
|
|
|
|
sourceBaseURI, getter_AddRefs(sourceBlobPrincipal))) {
|
|
|
|
|
nsCOMPtr<nsIURI> sourceBlobOwnerURI;
|
2020-04-27 13:54:47 +03:00
|
|
|
|
auto* basePrin = BasePrincipal::Cast(sourceBlobPrincipal);
|
|
|
|
|
rv = basePrin->GetURI(getter_AddRefs(sourceBlobOwnerURI));
|
2018-07-24 23:15:57 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
sourceBaseURI = sourceBlobOwnerURI;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
2018-07-24 23:15:57 +03:00
|
|
|
|
nsCOMPtr<nsIPrincipal> targetBlobPrincipal;
|
|
|
|
|
if (BlobURLProtocolHandler::GetBlobURLPrincipal(
|
|
|
|
|
targetBaseURI, getter_AddRefs(targetBlobPrincipal))) {
|
|
|
|
|
nsCOMPtr<nsIURI> targetBlobOwnerURI;
|
2020-04-27 13:54:47 +03:00
|
|
|
|
auto* basePrin = BasePrincipal::Cast(targetBlobPrincipal);
|
|
|
|
|
rv = basePrin->GetURI(getter_AddRefs(targetBlobOwnerURI));
|
2018-07-24 23:15:57 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
targetBaseURI = targetBlobOwnerURI;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
if (!sourceBaseURI || !targetBaseURI) return false;
|
|
|
|
|
|
|
|
|
|
// Compare schemes
|
|
|
|
|
nsAutoCString targetScheme;
|
|
|
|
|
bool sameScheme = false;
|
|
|
|
|
if (NS_FAILED(targetBaseURI->GetScheme(targetScheme)) ||
|
|
|
|
|
NS_FAILED(sourceBaseURI->SchemeIs(targetScheme.get(), &sameScheme)) ||
|
|
|
|
|
!sameScheme) {
|
|
|
|
|
// Not same-origin if schemes differ
|
|
|
|
|
return false;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
// For file scheme, reject unless the files are identical. See
|
|
|
|
|
// NS_RelaxStrictFileOriginPolicy for enforcing file same-origin checking
|
|
|
|
|
if (targetScheme.EqualsLiteral("file")) {
|
|
|
|
|
// in traditional unsafe behavior all files are the same origin
|
|
|
|
|
if (!aStrictFileOriginPolicy) return true;
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFileURL> sourceFileURL(do_QueryInterface(sourceBaseURI));
|
|
|
|
|
nsCOMPtr<nsIFileURL> targetFileURL(do_QueryInterface(targetBaseURI));
|
|
|
|
|
|
|
|
|
|
if (!sourceFileURL || !targetFileURL) return false;
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFile> sourceFile, targetFile;
|
|
|
|
|
|
|
|
|
|
sourceFileURL->GetFile(getter_AddRefs(sourceFile));
|
|
|
|
|
targetFileURL->GetFile(getter_AddRefs(targetFile));
|
|
|
|
|
|
|
|
|
|
if (!sourceFile || !targetFile) return false;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
// Otherwise they had better match
|
|
|
|
|
bool filesAreEqual = false;
|
2018-07-31 11:27:00 +03:00
|
|
|
|
rv = sourceFile->Equals(targetFile, &filesAreEqual);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return NS_SUCCEEDED(rv) && filesAreEqual;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-18 00:25:48 +03:00
|
|
|
|
#if IS_ORIGIN_IS_FULL_SPEC_DEFINED
|
2016-01-20 22:02:23 +03:00
|
|
|
|
bool hasFlag;
|
|
|
|
|
if (NS_FAILED(NS_URIChainHasFlags(
|
|
|
|
|
targetBaseURI, nsIProtocolHandler::ORIGIN_IS_FULL_SPEC, &hasFlag)) ||
|
|
|
|
|
hasFlag) {
|
|
|
|
|
// URIs with this flag have the whole spec as a distinct trust
|
|
|
|
|
// domain; use the whole spec for comparison
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsAutoCString targetSpec;
|
|
|
|
|
nsAutoCString sourceSpec;
|
|
|
|
|
return (NS_SUCCEEDED(targetBaseURI->GetSpec(targetSpec)) &&
|
|
|
|
|
NS_SUCCEEDED(sourceBaseURI->GetSpec(sourceSpec)) &&
|
|
|
|
|
targetSpec.Equals(sourceSpec));
|
|
|
|
|
}
|
2017-02-18 00:25:48 +03:00
|
|
|
|
#endif
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
// Compare hosts
|
|
|
|
|
nsAutoCString targetHost;
|
|
|
|
|
nsAutoCString sourceHost;
|
|
|
|
|
if (NS_FAILED(targetBaseURI->GetAsciiHost(targetHost)) ||
|
|
|
|
|
NS_FAILED(sourceBaseURI->GetAsciiHost(sourceHost))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIStandardURL> targetURL(do_QueryInterface(targetBaseURI));
|
|
|
|
|
nsCOMPtr<nsIStandardURL> sourceURL(do_QueryInterface(sourceBaseURI));
|
|
|
|
|
if (!targetURL || !sourceURL) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-27 21:11:12 +03:00
|
|
|
|
if (!targetHost.Equals(sourceHost, nsCaseInsensitiveCStringComparator)) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_GetRealPort(targetBaseURI) == NS_GetRealPort(sourceBaseURI);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NS_URIIsLocalFile(nsIURI* aURI) {
|
|
|
|
|
nsCOMPtr<nsINetUtil> util = do_GetNetUtil();
|
|
|
|
|
|
|
|
|
|
bool isFile;
|
|
|
|
|
return util &&
|
|
|
|
|
NS_SUCCEEDED(util->ProtocolHasFlags(
|
|
|
|
|
aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile)) &&
|
|
|
|
|
isFile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NS_RelaxStrictFileOriginPolicy(nsIURI* aTargetURI, nsIURI* aSourceURI,
|
|
|
|
|
bool aAllowDirectoryTarget /* = false */) {
|
|
|
|
|
if (!NS_URIIsLocalFile(aTargetURI)) {
|
|
|
|
|
// This is probably not what the caller intended
|
2018-06-18 08:43:11 +03:00
|
|
|
|
MOZ_ASSERT_UNREACHABLE(
|
|
|
|
|
"NS_RelaxStrictFileOriginPolicy called with non-file URI");
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!NS_URIIsLocalFile(aSourceURI)) {
|
|
|
|
|
// If the source is not also a file: uri then forget it
|
|
|
|
|
// (don't want resource: principals in a file: doc)
|
|
|
|
|
//
|
|
|
|
|
// note: we're not de-nesting jar: uris here, we want to
|
|
|
|
|
// keep archive content bottled up in its own little island
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// pull out the internal files
|
|
|
|
|
//
|
|
|
|
|
nsCOMPtr<nsIFileURL> targetFileURL(do_QueryInterface(aTargetURI));
|
|
|
|
|
nsCOMPtr<nsIFileURL> sourceFileURL(do_QueryInterface(aSourceURI));
|
|
|
|
|
nsCOMPtr<nsIFile> targetFile;
|
|
|
|
|
nsCOMPtr<nsIFile> sourceFile;
|
|
|
|
|
bool targetIsDir;
|
|
|
|
|
|
|
|
|
|
// Make sure targetFile is not a directory (bug 209234)
|
|
|
|
|
// and that it exists w/out unescaping (bug 395343)
|
|
|
|
|
if (!sourceFileURL || !targetFileURL ||
|
|
|
|
|
NS_FAILED(targetFileURL->GetFile(getter_AddRefs(targetFile))) ||
|
|
|
|
|
NS_FAILED(sourceFileURL->GetFile(getter_AddRefs(sourceFile))) ||
|
|
|
|
|
!targetFile || !sourceFile || NS_FAILED(targetFile->Normalize()) ||
|
|
|
|
|
#ifndef MOZ_WIDGET_ANDROID
|
|
|
|
|
NS_FAILED(sourceFile->Normalize()) ||
|
|
|
|
|
#endif
|
|
|
|
|
(!aAllowDirectoryTarget &&
|
|
|
|
|
(NS_FAILED(targetFile->IsDirectory(&targetIsDir)) || targetIsDir))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NS_IsInternalSameURIRedirect(nsIChannel* aOldChannel,
|
|
|
|
|
nsIChannel* aNewChannel, uint32_t aFlags) {
|
|
|
|
|
if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> oldURI, newURI;
|
|
|
|
|
aOldChannel->GetURI(getter_AddRefs(oldURI));
|
|
|
|
|
aNewChannel->GetURI(getter_AddRefs(newURI));
|
|
|
|
|
|
|
|
|
|
if (!oldURI || !newURI) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool res;
|
|
|
|
|
return NS_SUCCEEDED(oldURI->Equals(newURI, &res)) && res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NS_IsHSTSUpgradeRedirect(nsIChannel* aOldChannel, nsIChannel* aNewChannel,
|
|
|
|
|
uint32_t aFlags) {
|
|
|
|
|
if (!(aFlags & nsIChannelEventSink::REDIRECT_STS_UPGRADE)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> oldURI, newURI;
|
|
|
|
|
aOldChannel->GetURI(getter_AddRefs(oldURI));
|
|
|
|
|
aNewChannel->GetURI(getter_AddRefs(newURI));
|
|
|
|
|
|
|
|
|
|
if (!oldURI || !newURI) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-08 16:02:36 +03:00
|
|
|
|
if (!oldURI->SchemeIs("http")) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> upgradedURI;
|
2016-03-11 02:23:45 +03:00
|
|
|
|
nsresult rv = NS_GetSecureUpgradedURI(oldURI, getter_AddRefs(upgradedURI));
|
2016-02-18 06:03:41 +03:00
|
|
|
|
if (NS_FAILED(rv)) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool res;
|
|
|
|
|
return NS_SUCCEEDED(upgradedURI->Equals(newURI, &res)) && res;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 16:18:56 +03:00
|
|
|
|
nsresult NS_LinkRedirectChannels(uint64_t channelId,
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsIParentChannel* parentChannel,
|
|
|
|
|
nsIChannel** _result) {
|
|
|
|
|
nsCOMPtr<nsIRedirectChannelRegistrar> registrar =
|
2018-08-22 07:37:28 +03:00
|
|
|
|
RedirectChannelRegistrar::GetOrCreate();
|
|
|
|
|
MOZ_ASSERT(registrar);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
return registrar->LinkChannels(channelId, parentChannel, _result);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-12 19:08:25 +03:00
|
|
|
|
nsresult NS_MaybeOpenChannelUsingOpen(nsIChannel* aChannel,
|
2016-06-28 20:03:56 +03:00
|
|
|
|
nsIInputStream** aStream) {
|
2019-02-20 15:27:25 +03:00
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
2016-06-28 20:03:56 +03:00
|
|
|
|
return aChannel->Open(aStream);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-12 19:08:25 +03:00
|
|
|
|
nsresult NS_MaybeOpenChannelUsingAsyncOpen(nsIChannel* aChannel,
|
2016-06-28 20:03:56 +03:00
|
|
|
|
nsIStreamListener* aListener) {
|
2019-02-20 15:27:25 +03:00
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
2019-02-12 19:08:25 +03:00
|
|
|
|
return aChannel->AsyncOpen(aListener);
|
2016-06-28 20:03:56 +03:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-01 09:18:51 +03:00
|
|
|
|
nsILoadInfo::CrossOriginEmbedderPolicy
|
|
|
|
|
NS_GetCrossOriginEmbedderPolicyFromHeader(const nsACString& aHeader) {
|
|
|
|
|
nsCOMPtr<nsISFVService> sfv = GetSFVService();
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsISFVItem> item;
|
|
|
|
|
nsresult rv = sfv->ParseItem(aHeader, getter_AddRefs(item));
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
return nsILoadInfo::EMBEDDER_POLICY_NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsISFVBareItem> value;
|
|
|
|
|
rv = item->GetValue(getter_AddRefs(value));
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
return nsILoadInfo::EMBEDDER_POLICY_NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsISFVToken> token = do_QueryInterface(value);
|
|
|
|
|
if (!token) {
|
|
|
|
|
return nsILoadInfo::EMBEDDER_POLICY_NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsAutoCString embedderPolicy;
|
|
|
|
|
rv = token->GetValue(embedderPolicy);
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
return nsILoadInfo::EMBEDDER_POLICY_NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return embedderPolicy.EqualsLiteral("require-corp")
|
|
|
|
|
? nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP
|
|
|
|
|
: nsILoadInfo::EMBEDDER_POLICY_NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
/** Given the first (disposition) token from a Content-Disposition header,
|
|
|
|
|
* tell whether it indicates the content is inline or attachment
|
|
|
|
|
* @param aDispToken the disposition token from the content-disposition header
|
|
|
|
|
*/
|
|
|
|
|
uint32_t NS_GetContentDispositionFromToken(const nsAString& aDispToken) {
|
|
|
|
|
// RFC 2183, section 2.8 says that an unknown disposition
|
|
|
|
|
// value should be treated as "attachment"
|
|
|
|
|
// If all of these tests eval to false, then we have a content-disposition of
|
|
|
|
|
// "attachment" or unknown
|
|
|
|
|
if (aDispToken.IsEmpty() || aDispToken.LowerCaseEqualsLiteral("inline") ||
|
|
|
|
|
// Broken sites just send
|
|
|
|
|
// Content-Disposition: filename="file"
|
|
|
|
|
// without a disposition token... screen those out.
|
2021-06-04 15:35:16 +03:00
|
|
|
|
StringHead(aDispToken, 8).LowerCaseEqualsLiteral("filename")) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return nsIChannel::DISPOSITION_INLINE;
|
2021-06-04 15:35:16 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
return nsIChannel::DISPOSITION_ATTACHMENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t NS_GetContentDispositionFromHeader(const nsACString& aHeader,
|
|
|
|
|
nsIChannel* aChan /* = nullptr */) {
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
|
|
|
|
|
do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
|
|
|
|
|
if (NS_FAILED(rv)) return nsIChannel::DISPOSITION_ATTACHMENT;
|
|
|
|
|
|
|
|
|
|
nsAutoString dispToken;
|
2020-09-23 18:17:15 +03:00
|
|
|
|
rv = mimehdrpar->GetParameterHTTP(aHeader, "", ""_ns, true, nullptr,
|
2015-05-20 05:48:00 +03:00
|
|
|
|
dispToken);
|
|
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
// special case (see bug 272541): empty disposition type handled as "inline"
|
2021-06-04 15:35:16 +03:00
|
|
|
|
if (rv == NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return nsIChannel::DISPOSITION_INLINE;
|
2021-06-04 15:35:16 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return nsIChannel::DISPOSITION_ATTACHMENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_GetContentDispositionFromToken(dispToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_GetFilenameFromDisposition(nsAString& aFilename,
|
2020-03-09 17:33:25 +03:00
|
|
|
|
const nsACString& aDisposition) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
aFilename.Truncate();
|
|
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
|
nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
|
|
|
|
|
do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
|
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
|
|
// Get the value of 'filename' parameter
|
2020-09-23 18:17:15 +03:00
|
|
|
|
rv = mimehdrpar->GetParameterHTTP(aDisposition, "filename", ""_ns, true,
|
|
|
|
|
nullptr, aFilename);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
aFilename.Truncate();
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aFilename.IsEmpty()) return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
|
2020-02-06 21:23:45 +03:00
|
|
|
|
// Filename may still be percent-encoded. Fix:
|
|
|
|
|
if (aFilename.FindChar('%') != -1) {
|
|
|
|
|
nsCOMPtr<nsITextToSubURI> textToSubURI =
|
|
|
|
|
do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
nsAutoString unescaped;
|
2020-03-19 13:45:28 +03:00
|
|
|
|
textToSubURI->UnEscapeURIForUI(NS_ConvertUTF16toUTF8(aFilename),
|
2020-02-06 21:23:45 +03:00
|
|
|
|
unescaped);
|
|
|
|
|
aFilename.Assign(unescaped);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void net_EnsurePSMInit() {
|
2020-03-17 19:32:32 +03:00
|
|
|
|
if (XRE_IsSocketProcess()) {
|
|
|
|
|
EnsureNSSInitializedChromeOrContent();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
2021-01-15 13:28:41 +03:00
|
|
|
|
DebugOnly<bool> rv = EnsureNSSInitializedChromeOrContent();
|
|
|
|
|
MOZ_ASSERT(rv);
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NS_IsAboutBlank(nsIURI* uri) {
|
|
|
|
|
// GetSpec can be expensive for some URIs, so check the scheme first.
|
2019-08-08 16:02:36 +03:00
|
|
|
|
if (!uri->SchemeIs("about")) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-26 09:02:32 +03:00
|
|
|
|
return uri->GetSpecOrDefault().EqualsLiteral("about:blank");
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult NS_GenerateHostPort(const nsCString& host, int32_t port,
|
|
|
|
|
nsACString& hostLine) {
|
|
|
|
|
if (strchr(host.get(), ':')) {
|
|
|
|
|
// host is an IPv6 address literal and must be encapsulated in []'s
|
|
|
|
|
hostLine.Assign('[');
|
|
|
|
|
// scope id is not needed for Host header.
|
|
|
|
|
int scopeIdPos = host.FindChar('%');
|
2021-06-04 15:35:16 +03:00
|
|
|
|
if (scopeIdPos == -1) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
hostLine.Append(host);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
} else if (scopeIdPos > 0) {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
hostLine.Append(Substring(host, 0, scopeIdPos));
|
2021-06-04 15:35:16 +03:00
|
|
|
|
} else {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
return NS_ERROR_MALFORMED_URI;
|
2021-06-04 15:35:16 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
hostLine.Append(']');
|
2021-06-04 15:35:16 +03:00
|
|
|
|
} else {
|
2015-05-20 05:48:00 +03:00
|
|
|
|
hostLine.Assign(host);
|
2021-06-04 15:35:16 +03:00
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
if (port != -1) {
|
|
|
|
|
hostLine.Append(':');
|
|
|
|
|
hostLine.AppendInt(port);
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NS_SniffContent(const char* aSnifferType, nsIRequest* aRequest,
|
|
|
|
|
const uint8_t* aData, uint32_t aLength,
|
|
|
|
|
nsACString& aSniffedType) {
|
2021-06-04 15:35:16 +03:00
|
|
|
|
using ContentSnifferCache = nsCategoryCache<nsIContentSniffer>;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
extern ContentSnifferCache* gNetSniffers;
|
|
|
|
|
extern ContentSnifferCache* gDataSniffers;
|
2021-03-30 03:52:32 +03:00
|
|
|
|
extern ContentSnifferCache* gORBSniffers;
|
|
|
|
|
extern ContentSnifferCache* gNetAndORBSniffers;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
ContentSnifferCache* cache = nullptr;
|
|
|
|
|
if (!strcmp(aSnifferType, NS_CONTENT_SNIFFER_CATEGORY)) {
|
|
|
|
|
if (!gNetSniffers) {
|
|
|
|
|
gNetSniffers = new ContentSnifferCache(NS_CONTENT_SNIFFER_CATEGORY);
|
|
|
|
|
}
|
|
|
|
|
cache = gNetSniffers;
|
|
|
|
|
} else if (!strcmp(aSnifferType, NS_DATA_SNIFFER_CATEGORY)) {
|
|
|
|
|
if (!gDataSniffers) {
|
|
|
|
|
gDataSniffers = new ContentSnifferCache(NS_DATA_SNIFFER_CATEGORY);
|
|
|
|
|
}
|
|
|
|
|
cache = gDataSniffers;
|
2021-03-30 03:52:32 +03:00
|
|
|
|
} else if (!strcmp(aSnifferType, NS_ORB_SNIFFER_CATEGORY)) {
|
|
|
|
|
if (!gORBSniffers) {
|
|
|
|
|
gORBSniffers = new ContentSnifferCache(NS_ORB_SNIFFER_CATEGORY);
|
|
|
|
|
}
|
|
|
|
|
cache = gORBSniffers;
|
|
|
|
|
} else if (!strcmp(aSnifferType, NS_CONTENT_AND_ORB_SNIFFER_CATEGORY)) {
|
|
|
|
|
if (!gNetAndORBSniffers) {
|
|
|
|
|
gNetAndORBSniffers =
|
|
|
|
|
new ContentSnifferCache(NS_CONTENT_AND_ORB_SNIFFER_CATEGORY);
|
|
|
|
|
}
|
|
|
|
|
cache = gNetAndORBSniffers;
|
2015-05-20 05:48:00 +03:00
|
|
|
|
} else {
|
|
|
|
|
// Invalid content sniffer type was requested
|
|
|
|
|
MOZ_ASSERT(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-24 15:26:22 +03:00
|
|
|
|
// In case XCTO nosniff was present, we could just skip sniffing here
|
|
|
|
|
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
|
|
|
|
if (channel) {
|
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
2019-09-30 13:41:51 +03:00
|
|
|
|
if (loadInfo->GetSkipContentSniffing()) {
|
|
|
|
|
/* Bug 1571742
|
|
|
|
|
* We cannot skip snffing if the current MIME-Type might be a JSON.
|
|
|
|
|
* The JSON-Viewer relies on its own sniffer to determine, if it can
|
|
|
|
|
* render the page, so we need to make an exception if the Server provides
|
|
|
|
|
* a application/ mime, as it might be json.
|
|
|
|
|
*/
|
|
|
|
|
nsAutoCString currentContentType;
|
|
|
|
|
channel->GetContentType(currentContentType);
|
2020-02-12 19:20:46 +03:00
|
|
|
|
if (!StringBeginsWith(currentContentType, "application/"_ns)) {
|
2019-09-30 13:41:51 +03:00
|
|
|
|
return;
|
|
|
|
|
}
|
2019-09-24 15:26:22 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
nsCOMArray<nsIContentSniffer> sniffers;
|
|
|
|
|
cache->GetEntries(sniffers);
|
|
|
|
|
for (int32_t i = 0; i < sniffers.Count(); ++i) {
|
|
|
|
|
nsresult rv = sniffers[i]->GetMIMETypeFromContent(aRequest, aData, aLength,
|
|
|
|
|
aSniffedType);
|
|
|
|
|
if (NS_SUCCEEDED(rv) && !aSniffedType.IsEmpty()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aSniffedType.Truncate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NS_IsSrcdocChannel(nsIChannel* aChannel) {
|
|
|
|
|
bool isSrcdoc;
|
|
|
|
|
nsCOMPtr<nsIInputStreamChannel> isr = do_QueryInterface(aChannel);
|
|
|
|
|
if (isr) {
|
|
|
|
|
isr->GetIsSrcdocChannel(&isSrcdoc);
|
|
|
|
|
return isSrcdoc;
|
|
|
|
|
}
|
|
|
|
|
nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(aChannel);
|
|
|
|
|
if (vsc) {
|
2016-11-23 12:21:17 +03:00
|
|
|
|
nsresult rv = vsc->GetIsSrcdocChannel(&isSrcdoc);
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
|
return isSrcdoc;
|
|
|
|
|
}
|
2015-05-20 05:48:00 +03:00
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-11 16:51:53 +03:00
|
|
|
|
// helper function for NS_ShouldSecureUpgrade for checking HSTS
|
2021-08-10 17:00:22 +03:00
|
|
|
|
bool handleResultFunc(bool aAllowSTS, bool aIsStsHost, uint32_t aHstsSource) {
|
|
|
|
|
if (aIsStsHost) {
|
|
|
|
|
LOG(("nsHttpChannel::Connect() STS permissions found\n"));
|
|
|
|
|
if (aAllowSTS) {
|
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
|
Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::STS);
|
|
|
|
|
switch (aHstsSource) {
|
|
|
|
|
case nsISiteSecurityService::SOURCE_PRELOAD_LIST:
|
|
|
|
|
Telemetry::Accumulate(Telemetry::HSTS_UPGRADE_SOURCE, 0);
|
|
|
|
|
break;
|
|
|
|
|
case nsISiteSecurityService::SOURCE_ORGANIC_REQUEST:
|
|
|
|
|
Telemetry::Accumulate(Telemetry::HSTS_UPGRADE_SOURCE, 1);
|
|
|
|
|
break;
|
|
|
|
|
case nsISiteSecurityService::SOURCE_UNKNOWN:
|
|
|
|
|
default:
|
|
|
|
|
// record this as an organic request
|
|
|
|
|
Telemetry::Accumulate(Telemetry::HSTS_UPGRADE_SOURCE, 1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
|
Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::PrefBlockedSTS);
|
|
|
|
|
} else {
|
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
|
Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::NoReasonToUpgrade);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
2021-10-11 16:51:53 +03:00
|
|
|
|
// That function is a helper function of NS_ShouldSecureUpgrade to check if
|
|
|
|
|
// CSP upgrade-insecure-requests, Mixed content auto upgrading or HTTPs-Only/-
|
|
|
|
|
// First should upgrade the given request.
|
|
|
|
|
static bool ShouldSecureUpgradeNoHSTS(nsIURI* aURI, nsILoadInfo* aLoadInfo) {
|
|
|
|
|
// 2. CSP upgrade-insecure-requests
|
|
|
|
|
if (aLoadInfo->GetUpgradeInsecureRequests()) {
|
|
|
|
|
// let's log a message to the console that we are upgrading a request
|
|
|
|
|
nsAutoCString scheme;
|
|
|
|
|
aURI->GetScheme(scheme);
|
|
|
|
|
// append the additional 's' for security to the scheme :-)
|
|
|
|
|
scheme.AppendLiteral("s");
|
|
|
|
|
NS_ConvertUTF8toUTF16 reportSpec(aURI->GetSpecOrDefault());
|
|
|
|
|
NS_ConvertUTF8toUTF16 reportScheme(scheme);
|
|
|
|
|
AutoTArray<nsString, 2> params = {reportSpec, reportScheme};
|
|
|
|
|
uint32_t innerWindowId = aLoadInfo->GetInnerWindowID();
|
|
|
|
|
CSP_LogLocalizedStr("upgradeInsecureRequest", params,
|
|
|
|
|
u""_ns, // aSourceFile
|
|
|
|
|
u""_ns, // aScriptSample
|
|
|
|
|
0, // aLineNumber
|
|
|
|
|
0, // aColumnNumber
|
|
|
|
|
nsIScriptError::warningFlag,
|
|
|
|
|
"upgradeInsecureRequest"_ns, innerWindowId,
|
|
|
|
|
!!aLoadInfo->GetOriginAttributes().mPrivateBrowsingId);
|
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
|
Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::CSP);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// 3. Mixed content auto upgrading
|
|
|
|
|
if (aLoadInfo->GetBrowserUpgradeInsecureRequests()) {
|
|
|
|
|
// let's log a message to the console that we are upgrading a request
|
|
|
|
|
nsAutoCString scheme;
|
|
|
|
|
aURI->GetScheme(scheme);
|
|
|
|
|
// append the additional 's' for security to the scheme :-)
|
|
|
|
|
scheme.AppendLiteral("s");
|
|
|
|
|
NS_ConvertUTF8toUTF16 reportSpec(aURI->GetSpecOrDefault());
|
|
|
|
|
NS_ConvertUTF8toUTF16 reportScheme(scheme);
|
|
|
|
|
AutoTArray<nsString, 2> params = {reportSpec, reportScheme};
|
|
|
|
|
|
|
|
|
|
nsAutoString localizedMsg;
|
|
|
|
|
nsContentUtils::FormatLocalizedString(nsContentUtils::eSECURITY_PROPERTIES,
|
|
|
|
|
"MixedContentAutoUpgrade", params,
|
|
|
|
|
localizedMsg);
|
|
|
|
|
|
|
|
|
|
// Prepending ixed Content to the outgoing console message
|
|
|
|
|
nsString message;
|
|
|
|
|
message.AppendLiteral(u"Mixed Content: ");
|
|
|
|
|
message.Append(localizedMsg);
|
|
|
|
|
|
|
|
|
|
uint32_t innerWindowId = aLoadInfo->GetInnerWindowID();
|
|
|
|
|
nsContentUtils::ReportToConsoleByWindowID(
|
|
|
|
|
message, nsIScriptError::warningFlag, "Mixed Content Message"_ns,
|
|
|
|
|
innerWindowId, aURI);
|
|
|
|
|
|
|
|
|
|
// Set this flag so we know we'll upgrade because of
|
|
|
|
|
// 'security.mixed_content.upgrade_display_content'.
|
|
|
|
|
aLoadInfo->SetBrowserDidUpgradeInsecureRequests(true);
|
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
|
Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::BrowserDisplay);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. Https-Only / -First
|
|
|
|
|
if (nsHTTPSOnlyUtils::ShouldUpgradeRequest(aURI, aLoadInfo) ||
|
|
|
|
|
nsHTTPSOnlyUtils::ShouldUpgradeHttpsFirstRequest(aURI, aLoadInfo)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-08-10 17:00:22 +03:00
|
|
|
|
|
2021-10-11 16:51:53 +03:00
|
|
|
|
// Check if channel should be upgraded. check in the following order:
|
|
|
|
|
// 1. HSTS
|
|
|
|
|
// 2. CSP upgrade-insecure-requests
|
|
|
|
|
// 3. Mixed content auto upgrading
|
|
|
|
|
// 4. Https-Only / first
|
|
|
|
|
// (5. Https RR - will be checked in nsHttpChannel)
|
|
|
|
|
nsresult NS_ShouldSecureUpgrade(
|
|
|
|
|
nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIPrincipal* aChannelResultPrincipal,
|
|
|
|
|
bool aPrivateBrowsing, bool aAllowSTS,
|
|
|
|
|
const OriginAttributes& aOriginAttributes, bool& aShouldUpgrade,
|
2021-08-10 17:00:22 +03:00
|
|
|
|
std::function<void(bool, nsresult)>&& aResultCallback,
|
|
|
|
|
bool& aWillCallback) {
|
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
2021-10-11 16:51:53 +03:00
|
|
|
|
if (!XRE_IsParentProcess()) {
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aWillCallback = false;
|
|
|
|
|
aShouldUpgrade = false;
|
|
|
|
|
|
|
|
|
|
// Even if we're in private browsing mode, we still enforce existing STS
|
|
|
|
|
// data (it is read-only).
|
|
|
|
|
// if the connection is not using SSL and either the exact host matches or
|
|
|
|
|
// a superdomain wants to force HTTPS, do it.
|
|
|
|
|
bool isHttps = aURI->SchemeIs("https");
|
|
|
|
|
|
|
|
|
|
// If request is https, then there is nothing to do here.
|
|
|
|
|
if (isHttps) {
|
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
|
Telemetry::LABELS_HTTP_SCHEME_UPGRADE_TYPE::AlreadyHTTPS);
|
|
|
|
|
aShouldUpgrade = false;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
// If it is a mixed content trustworthy loopback, then we shouldn't upgrade
|
|
|
|
|
// it.
|
|
|
|
|
if (nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI)) {
|
|
|
|
|
aShouldUpgrade = false;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
// If no loadInfo exist there is nothing to upgrade here.
|
|
|
|
|
if (!aLoadInfo) {
|
|
|
|
|
aShouldUpgrade = false;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2021-08-10 17:00:22 +03:00
|
|
|
|
MOZ_ASSERT(!aURI->SchemeIs("https"));
|
|
|
|
|
|
|
|
|
|
// enforce Strict-Transport-Security
|
|
|
|
|
nsISiteSecurityService* sss = gHttpHandler->GetSSService();
|
|
|
|
|
NS_ENSURE_TRUE(sss, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
|
|
|
|
|
bool isStsHost = false;
|
|
|
|
|
uint32_t hstsSource = 0;
|
|
|
|
|
uint32_t flags =
|
|
|
|
|
aPrivateBrowsing ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
|
|
|
|
|
// Calling |IsSecureURI| before the storage is ready to read will
|
|
|
|
|
// block the main thread. Once the storage is ready, we can call it
|
|
|
|
|
// from main thread.
|
|
|
|
|
static Atomic<bool, Relaxed> storageReady(false);
|
|
|
|
|
if (!storageReady && gSocketTransportService && aResultCallback) {
|
2021-10-11 16:51:53 +03:00
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aLoadInfo;
|
2021-08-10 17:00:22 +03:00
|
|
|
|
nsCOMPtr<nsIURI> uri = aURI;
|
2021-10-11 16:51:53 +03:00
|
|
|
|
auto callbackWrapper = [resultCallback{std::move(aResultCallback)}, uri,
|
|
|
|
|
loadInfo](bool aShouldUpgrade, nsresult aStatus) {
|
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
|
|
// 1. HSTS upgrade
|
|
|
|
|
if (aShouldUpgrade || NS_FAILED(aStatus)) {
|
|
|
|
|
resultCallback(aShouldUpgrade, aStatus);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Check if we need to upgrade because of other reasons.
|
|
|
|
|
// 2. CSP upgrade-insecure-requests
|
|
|
|
|
// 3. Mixed content auto upgrading
|
|
|
|
|
// 4. Https-Only / first
|
|
|
|
|
bool shouldUpgrade = ShouldSecureUpgradeNoHSTS(uri, loadInfo);
|
|
|
|
|
resultCallback(shouldUpgrade, aStatus);
|
|
|
|
|
};
|
2021-08-10 17:00:22 +03:00
|
|
|
|
nsCOMPtr<nsISiteSecurityService> service = sss;
|
|
|
|
|
nsresult rv = gSocketTransportService->Dispatch(
|
|
|
|
|
NS_NewRunnableFunction(
|
|
|
|
|
"net::NS_ShouldSecureUpgrade",
|
|
|
|
|
[service{std::move(service)}, uri{std::move(uri)}, flags(flags),
|
|
|
|
|
originAttributes(aOriginAttributes),
|
|
|
|
|
handleResultFunc{std::move(handleResultFunc)},
|
2021-10-11 16:51:53 +03:00
|
|
|
|
callbackWrapper{std::move(callbackWrapper)},
|
2021-08-10 17:00:22 +03:00
|
|
|
|
allowSTS{std::move(aAllowSTS)}]() mutable {
|
2021-10-06 00:34:43 +03:00
|
|
|
|
bool isStsHost = false;
|
2021-10-11 16:51:53 +03:00
|
|
|
|
uint32_t hstsSource = 0;
|
2021-08-10 17:00:22 +03:00
|
|
|
|
nsresult rv =
|
|
|
|
|
service->IsSecureURI(uri, flags, originAttributes, nullptr,
|
|
|
|
|
&hstsSource, &isStsHost);
|
|
|
|
|
|
|
|
|
|
// Successfully get the result from |IsSecureURI| implies that
|
|
|
|
|
// the storage is ready to read.
|
|
|
|
|
storageReady = NS_SUCCEEDED(rv);
|
|
|
|
|
bool shouldUpgrade =
|
|
|
|
|
handleResultFunc(allowSTS, isStsHost, hstsSource);
|
2021-10-11 16:51:53 +03:00
|
|
|
|
// Check if request should be upgraded.
|
2021-08-10 17:00:22 +03:00
|
|
|
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
|
|
|
|
"net::NS_ShouldSecureUpgrade::ResultCallback",
|
|
|
|
|
[rv, shouldUpgrade,
|
2021-10-11 16:51:53 +03:00
|
|
|
|
callbackWrapper{std::move(callbackWrapper)}]() {
|
|
|
|
|
callbackWrapper(shouldUpgrade, rv);
|
2021-08-10 17:00:22 +03:00
|
|
|
|
}));
|
|
|
|
|
}),
|
|
|
|
|
NS_DISPATCH_NORMAL);
|
|
|
|
|
aWillCallback = NS_SUCCEEDED(rv);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsresult rv = sss->IsSecureURI(aURI, flags, aOriginAttributes, nullptr,
|
|
|
|
|
&hstsSource, &isStsHost);
|
|
|
|
|
|
|
|
|
|
// if the SSS check fails, it's likely because this load is on a
|
|
|
|
|
// malformed URI or something else in the setup is wrong, so any error
|
|
|
|
|
// should be reported.
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
|
|
aShouldUpgrade = handleResultFunc(aAllowSTS, isStsHost, hstsSource);
|
2021-10-11 16:51:53 +03:00
|
|
|
|
if (!aShouldUpgrade) {
|
|
|
|
|
// Check for CSP upgrade-insecure-requests, Mixed content auto upgrading
|
|
|
|
|
// and Https-Only / -First.
|
|
|
|
|
aShouldUpgrade = ShouldSecureUpgradeNoHSTS(aURI, aLoadInfo);
|
2021-10-06 00:34:43 +03:00
|
|
|
|
}
|
2021-10-11 16:51:53 +03:00
|
|
|
|
return rv;
|
2015-11-02 19:27:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-11 02:23:45 +03:00
|
|
|
|
nsresult NS_GetSecureUpgradedURI(nsIURI* aURI, nsIURI** aUpgradedURI) {
|
2018-01-24 22:33:02 +03:00
|
|
|
|
NS_MutateURI mutator(aURI);
|
|
|
|
|
mutator.SetScheme("https"_ns); // Change the scheme to HTTPS:
|
2016-03-11 02:23:45 +03:00
|
|
|
|
|
|
|
|
|
// Change the default port to 443:
|
2018-01-24 22:33:02 +03:00
|
|
|
|
nsCOMPtr<nsIStandardURL> stdURL = do_QueryInterface(aURI);
|
|
|
|
|
if (stdURL) {
|
2021-08-12 10:40:58 +03:00
|
|
|
|
mutator.Apply(&nsIStandardURLMutator::SetDefaultPort, 443, nullptr);
|
2016-03-11 02:23:45 +03:00
|
|
|
|
} else {
|
|
|
|
|
// If we don't have a nsStandardURL, fall back to using GetPort/SetPort.
|
|
|
|
|
// XXXdholbert Is this function even called with a non-nsStandardURL arg,
|
|
|
|
|
// in practice?
|
2018-01-24 22:33:02 +03:00
|
|
|
|
NS_WARNING("Calling NS_GetSecureUpgradedURI for non nsStandardURL");
|
2016-03-11 02:23:45 +03:00
|
|
|
|
int32_t oldPort = -1;
|
2018-01-24 22:33:02 +03:00
|
|
|
|
nsresult rv = aURI->GetPort(&oldPort);
|
2016-03-11 02:23:45 +03:00
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
|
|
// Keep any nonstandard ports so only the scheme is changed.
|
|
|
|
|
// For example:
|
|
|
|
|
// http://foo.com:80 -> https://foo.com:443
|
|
|
|
|
// http://foo.com:81 -> https://foo.com:81
|
|
|
|
|
|
|
|
|
|
if (oldPort == 80 || oldPort == -1) {
|
2018-01-24 22:33:02 +03:00
|
|
|
|
mutator.SetPort(-1);
|
2016-03-11 02:23:45 +03:00
|
|
|
|
} else {
|
2018-01-24 22:33:02 +03:00
|
|
|
|
mutator.SetPort(oldPort);
|
2016-03-11 02:23:45 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-24 22:33:02 +03:00
|
|
|
|
return mutator.Finalize(aUpgradedURI);
|
2016-03-11 02:23:45 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-13 11:23:26 +03:00
|
|
|
|
nsresult NS_CompareLoadInfoAndLoadContext(nsIChannel* aChannel) {
|
2019-02-20 15:27:25 +03:00
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
2016-04-13 11:23:26 +03:00
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsILoadContext> loadContext;
|
|
|
|
|
NS_QueryNotificationCallbacks(aChannel, loadContext);
|
2019-02-20 15:27:25 +03:00
|
|
|
|
if (!loadContext) {
|
2016-07-28 09:44:22 +03:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2016-04-13 11:23:26 +03:00
|
|
|
|
|
2017-05-17 18:39:22 +03:00
|
|
|
|
// We try to skip about:newtab.
|
2016-07-28 09:44:22 +03:00
|
|
|
|
// about:newtab will use SystemPrincipal to download thumbnails through
|
|
|
|
|
// https:// and blob URLs.
|
|
|
|
|
bool isAboutPage = false;
|
|
|
|
|
nsINode* node = loadInfo->LoadingNode();
|
|
|
|
|
if (node) {
|
2019-01-02 16:05:23 +03:00
|
|
|
|
nsIURI* uri = node->OwnerDoc()->GetDocumentURI();
|
2019-08-08 16:02:36 +03:00
|
|
|
|
isAboutPage = uri->SchemeIs("about");
|
2016-07-28 09:44:22 +03:00
|
|
|
|
}
|
2016-04-13 11:23:26 +03:00
|
|
|
|
|
2016-07-28 09:44:22 +03:00
|
|
|
|
if (isAboutPage) {
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2016-04-13 11:23:26 +03:00
|
|
|
|
|
2016-10-13 10:43:59 +03:00
|
|
|
|
// We skip the favicon loading here. The favicon loading might be
|
|
|
|
|
// triggered by the XUL image. For that case, the loadContext will have
|
|
|
|
|
// default originAttributes since the XUL image uses SystemPrincipal, but
|
|
|
|
|
// the loadInfo will use originAttributes from the content. Thus, the
|
|
|
|
|
// originAttributes between loadInfo and loadContext will be different.
|
|
|
|
|
// That's why we have to skip the comparison for the favicon loading.
|
2020-04-06 21:57:36 +03:00
|
|
|
|
if (loadInfo->GetLoadingPrincipal() &&
|
|
|
|
|
loadInfo->GetLoadingPrincipal()->IsSystemPrincipal() &&
|
2016-10-13 10:43:59 +03:00
|
|
|
|
loadInfo->InternalContentPolicyType() ==
|
|
|
|
|
nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON) {
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 09:44:22 +03:00
|
|
|
|
OriginAttributes originAttrsLoadInfo = loadInfo->GetOriginAttributes();
|
2017-01-12 19:38:48 +03:00
|
|
|
|
OriginAttributes originAttrsLoadContext;
|
2016-07-28 09:44:22 +03:00
|
|
|
|
loadContext->GetOriginAttributes(originAttrsLoadContext);
|
|
|
|
|
|
2016-11-20 00:53:32 +03:00
|
|
|
|
LOG(
|
2019-07-17 02:40:19 +03:00
|
|
|
|
("NS_CompareLoadInfoAndLoadContext - loadInfo: %d, %d; "
|
|
|
|
|
"loadContext: %d, %d. [channel=%p]",
|
2016-11-20 00:53:32 +03:00
|
|
|
|
originAttrsLoadInfo.mUserContextId,
|
2019-07-17 02:40:19 +03:00
|
|
|
|
originAttrsLoadInfo.mPrivateBrowsingId,
|
2016-08-04 09:05:38 +03:00
|
|
|
|
originAttrsLoadContext.mUserContextId,
|
|
|
|
|
originAttrsLoadContext.mPrivateBrowsingId, aChannel));
|
2016-07-28 09:44:22 +03:00
|
|
|
|
|
|
|
|
|
MOZ_ASSERT(originAttrsLoadInfo.mUserContextId ==
|
|
|
|
|
originAttrsLoadContext.mUserContextId,
|
|
|
|
|
"The value of mUserContextId in the loadContext and in the "
|
|
|
|
|
"loadInfo are not the same!");
|
|
|
|
|
|
2016-08-04 09:05:38 +03:00
|
|
|
|
MOZ_ASSERT(originAttrsLoadInfo.mPrivateBrowsingId ==
|
|
|
|
|
originAttrsLoadContext.mPrivateBrowsingId,
|
|
|
|
|
"The value of mPrivateBrowsingId in the loadContext and in the "
|
|
|
|
|
"loadInfo are not the same!");
|
|
|
|
|
|
2016-04-13 11:23:26 +03:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-06 10:22:18 +03:00
|
|
|
|
nsresult NS_SetRequestBlockingReason(nsIChannel* channel, uint32_t reason) {
|
2019-04-26 13:59:41 +03:00
|
|
|
|
NS_ENSURE_ARG(channel);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
|
|
|
|
return NS_SetRequestBlockingReason(loadInfo, reason);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-06 10:22:18 +03:00
|
|
|
|
nsresult NS_SetRequestBlockingReason(nsILoadInfo* loadInfo, uint32_t reason) {
|
2019-04-26 13:59:41 +03:00
|
|
|
|
NS_ENSURE_ARG(loadInfo);
|
|
|
|
|
|
|
|
|
|
return loadInfo->SetRequestBlockingReason(reason);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-06 10:22:18 +03:00
|
|
|
|
nsresult NS_SetRequestBlockingReasonIfNull(nsILoadInfo* loadInfo,
|
2019-04-26 13:59:41 +03:00
|
|
|
|
uint32_t reason) {
|
|
|
|
|
NS_ENSURE_ARG(loadInfo);
|
|
|
|
|
|
|
|
|
|
uint32_t existingReason;
|
|
|
|
|
if (NS_SUCCEEDED(loadInfo->GetRequestBlockingReason(&existingReason)) &&
|
|
|
|
|
existingReason != nsILoadInfo::BLOCKING_REASON_NONE) {
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return loadInfo->SetRequestBlockingReason(reason);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-02 17:32:37 +03:00
|
|
|
|
bool NS_IsOffline() {
|
|
|
|
|
bool offline = true;
|
|
|
|
|
bool connectivity = true;
|
|
|
|
|
nsCOMPtr<nsIIOService> ios = do_GetIOService();
|
|
|
|
|
if (ios) {
|
|
|
|
|
ios->GetOffline(&offline);
|
|
|
|
|
ios->GetConnectivity(&connectivity);
|
|
|
|
|
}
|
|
|
|
|
return offline || !connectivity;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-25 15:47:29 +03:00
|
|
|
|
/**
|
|
|
|
|
* This function returns true if this channel should be classified by
|
|
|
|
|
* the URL Classifier, false otherwise.
|
|
|
|
|
*
|
|
|
|
|
* The idea of the algorithm to determine if a channel should be
|
|
|
|
|
* classified is based on:
|
|
|
|
|
* 1. Channels created by non-privileged code should be classified.
|
|
|
|
|
* 2. Top-level document’s channels, if loaded by privileged code
|
|
|
|
|
* (system principal), should be classified.
|
|
|
|
|
* 3. Any other channel, created by privileged code, is considered safe.
|
|
|
|
|
*
|
|
|
|
|
* A bad/hacked/corrupted safebrowsing database, plus a mistakenly
|
|
|
|
|
* classified critical channel (this may result from a bug in the exemption
|
|
|
|
|
* rules or incorrect information being passed into) can cause serious
|
|
|
|
|
* problems. For example, if the updater channel is classified and blocked
|
|
|
|
|
* by the Safe Browsing, Firefox can't update itself, and there is no way to
|
|
|
|
|
* recover from that.
|
|
|
|
|
*
|
|
|
|
|
* So two safeguards are added to ensure critical channels are never
|
|
|
|
|
* automatically classified either because there is a bug in the algorithm
|
|
|
|
|
* or the data in loadinfo is wrong.
|
|
|
|
|
* 1. beConservative, this is set by ServiceRequest and we treat
|
|
|
|
|
* channel created for ServiceRequest as critical channels.
|
|
|
|
|
* 2. nsIChannel::LOAD_BYPASS_URL_CLASSIFIER, channel's opener can use this
|
|
|
|
|
* flag to enforce bypassing the URL classifier check.
|
|
|
|
|
*/
|
|
|
|
|
bool NS_ShouldClassifyChannel(nsIChannel* aChannel) {
|
2019-03-25 15:48:25 +03:00
|
|
|
|
nsLoadFlags loadFlags;
|
|
|
|
|
Unused << aChannel->GetLoadFlags(&loadFlags);
|
|
|
|
|
// If our load flags dictate that we must let this channel through without
|
|
|
|
|
// URL classification, obey that here without performing more checks.
|
|
|
|
|
if (loadFlags & nsIChannel::LOAD_BYPASS_URL_CLASSIFIER) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-25 15:47:29 +03:00
|
|
|
|
nsCOMPtr<nsIHttpChannelInternal> httpChannel(do_QueryInterface(aChannel));
|
|
|
|
|
if (httpChannel) {
|
|
|
|
|
bool beConservative;
|
|
|
|
|
nsresult rv = httpChannel->GetBeConservative(&beConservative);
|
|
|
|
|
|
2019-03-25 15:48:25 +03:00
|
|
|
|
// beConservative flag, set by ServiceRequest to ensure channels that
|
|
|
|
|
// fetch update use conservative TLS setting, are used here to identify
|
|
|
|
|
// channels are critical to bypass classification. for channels don't
|
|
|
|
|
// support beConservative, continue to apply the exemption rules.
|
2019-03-25 15:47:29 +03:00
|
|
|
|
if (NS_SUCCEEDED(rv) && beConservative) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
2021-01-15 15:07:16 +03:00
|
|
|
|
ExtContentPolicyType type = loadInfo->GetExternalContentPolicyType();
|
2019-10-22 17:04:09 +03:00
|
|
|
|
// Skip classifying channel triggered by system unless it is a top-level
|
|
|
|
|
// load.
|
2021-06-04 15:35:16 +03:00
|
|
|
|
return !(loadInfo->TriggeringPrincipal()->IsSystemPrincipal() &&
|
|
|
|
|
ExtContentPolicy::TYPE_DOCUMENT != type);
|
2019-03-25 15:47:29 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 05:48:00 +03:00
|
|
|
|
namespace mozilla {
|
|
|
|
|
namespace net {
|
|
|
|
|
|
|
|
|
|
bool InScriptableRange(int64_t val) {
|
|
|
|
|
return (val <= kJS_MAX_SAFE_INTEGER) && (val >= kJS_MIN_SAFE_INTEGER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool InScriptableRange(uint64_t val) { return val <= kJS_MAX_SAFE_UINTEGER; }
|
|
|
|
|
|
2018-08-06 22:31:22 +03:00
|
|
|
|
nsresult GetParameterHTTP(const nsACString& aHeaderVal, const char* aParamName,
|
|
|
|
|
nsAString& aResult) {
|
|
|
|
|
return nsMIMEHeaderParamImpl::GetParameterHTTP(aHeaderVal, aParamName,
|
|
|
|
|
aResult);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-26 04:24:42 +03:00
|
|
|
|
bool ChannelIsPost(nsIChannel* aChannel) {
|
|
|
|
|
if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel)) {
|
|
|
|
|
nsAutoCString method;
|
|
|
|
|
Unused << httpChannel->GetRequestMethod(method);
|
|
|
|
|
return method.EqualsLiteral("POST");
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-11 11:08:19 +03:00
|
|
|
|
bool SchemeIsHTTP(nsIURI* aURI) {
|
|
|
|
|
MOZ_ASSERT(aURI);
|
|
|
|
|
return aURI->SchemeIs("http");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SchemeIsHTTPS(nsIURI* aURI) {
|
|
|
|
|
MOZ_ASSERT(aURI);
|
|
|
|
|
return aURI->SchemeIs("https");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SchemeIsJavascript(nsIURI* aURI) {
|
|
|
|
|
MOZ_ASSERT(aURI);
|
|
|
|
|
return aURI->SchemeIs("javascript");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SchemeIsChrome(nsIURI* aURI) {
|
|
|
|
|
MOZ_ASSERT(aURI);
|
|
|
|
|
return aURI->SchemeIs("chrome");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SchemeIsAbout(nsIURI* aURI) {
|
|
|
|
|
MOZ_ASSERT(aURI);
|
|
|
|
|
return aURI->SchemeIs("about");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SchemeIsBlob(nsIURI* aURI) {
|
|
|
|
|
MOZ_ASSERT(aURI);
|
|
|
|
|
return aURI->SchemeIs("blob");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SchemeIsFile(nsIURI* aURI) {
|
|
|
|
|
MOZ_ASSERT(aURI);
|
|
|
|
|
return aURI->SchemeIs("file");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SchemeIsData(nsIURI* aURI) {
|
|
|
|
|
MOZ_ASSERT(aURI);
|
|
|
|
|
return aURI->SchemeIs("data");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SchemeIsViewSource(nsIURI* aURI) {
|
|
|
|
|
MOZ_ASSERT(aURI);
|
|
|
|
|
return aURI->SchemeIs("view-source");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SchemeIsResource(nsIURI* aURI) {
|
|
|
|
|
MOZ_ASSERT(aURI);
|
|
|
|
|
return aURI->SchemeIs("resource");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SchemeIsFTP(nsIURI* aURI) {
|
|
|
|
|
MOZ_ASSERT(aURI);
|
|
|
|
|
return aURI->SchemeIs("ftp");
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 18:25:42 +03:00
|
|
|
|
} // namespace net
|
2015-05-20 05:48:00 +03:00
|
|
|
|
} // namespace mozilla
|
2021-06-24 12:13:30 +03:00
|
|
|
|
|
|
|
|
|
nsresult NS_HasRootDomain(const nsACString& aInput, const nsACString& aHost,
|
|
|
|
|
bool* aResult) {
|
|
|
|
|
if (NS_WARN_IF(!aResult)) {
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*aResult = false;
|
|
|
|
|
|
|
|
|
|
// If the strings are the same, we obviously have a match.
|
|
|
|
|
if (aInput == aHost) {
|
|
|
|
|
*aResult = true;
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If aHost is not found, we know we do not have it as a root domain.
|
|
|
|
|
int32_t index = nsAutoCString(aInput).Find(aHost.BeginReading());
|
|
|
|
|
if (index == kNotFound) {
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Otherwise, we have aHost as our root domain iff the index of aHost is
|
|
|
|
|
// aHost.length subtracted from our length and (since we do not have an
|
|
|
|
|
// exact match) the character before the index is a dot or slash.
|
|
|
|
|
*aResult = index > 0 && (uint32_t)index == aInput.Length() - aHost.Length() &&
|
|
|
|
|
(aInput[index - 1] == '.' || aInput[index - 1] == '/');
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2021-08-03 19:46:34 +03:00
|
|
|
|
|
|
|
|
|
void CheckForBrokenChromeURL(nsILoadInfo* aLoadInfo, nsIURI* aURI) {
|
|
|
|
|
if (!aURI) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
nsAutoCString scheme;
|
|
|
|
|
aURI->GetScheme(scheme);
|
|
|
|
|
if (!scheme.EqualsLiteral("chrome") && !scheme.EqualsLiteral("resource")) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
nsAutoCString host;
|
|
|
|
|
aURI->GetHost(host);
|
|
|
|
|
// Ignore test hits.
|
|
|
|
|
if (host.EqualsLiteral("mochitests") || host.EqualsLiteral("reftest")) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsAutoCString filePath;
|
|
|
|
|
aURI->GetFilePath(filePath);
|
|
|
|
|
// Fluent likes checking for files everywhere and expects failure.
|
|
|
|
|
if (StringEndsWith(filePath, ".ftl"_ns)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ignore fetches/xhrs, as they are frequently used in a way where
|
|
|
|
|
// non-existence is OK (ie with fallbacks). This risks false negatives (ie
|
|
|
|
|
// files that *should* be there but aren't) - which we accept for now.
|
|
|
|
|
ExtContentPolicy policy = aLoadInfo
|
|
|
|
|
? aLoadInfo->GetExternalContentPolicyType()
|
|
|
|
|
: ExtContentPolicy::TYPE_OTHER;
|
|
|
|
|
if (policy == ExtContentPolicy::TYPE_FETCH ||
|
|
|
|
|
policy == ExtContentPolicy::TYPE_XMLHTTPREQUEST) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsCString spec;
|
|
|
|
|
aURI->GetSpec(spec);
|
|
|
|
|
|
|
|
|
|
// DTD files from gre may not exist when requested by tests.
|
|
|
|
|
if (StringBeginsWith(spec, "resource://gre/res/dtd/"_ns)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (xpc::IsInAutomation()) {
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
if (NS_IsMainThread()) {
|
|
|
|
|
nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
|
|
|
|
|
Unused << xpc->DebugDumpJSStack(false, false, false);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
MOZ_CRASH_UNSAFE_PRINTF("Missing chrome or resource URLs: %s", spec.get());
|
|
|
|
|
} else {
|
|
|
|
|
printf_stderr("Missing chrome or resource URL: %s\n", spec.get());
|
|
|
|
|
}
|
|
|
|
|
}
|