--- a/caps/DomainPolicy.cpp
+++ b/caps/DomainPolicy.cpp
@@ -4,16 +4,17 @@
* 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/. */
#include "DomainPolicy.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/Unused.h"
#include "nsIMessageManager.h"
+#include "nsIURIMutator.h"
#include "nsScriptSecurityManager.h"
namespace mozilla {
using namespace ipc;
using namespace dom;
NS_IMPL_ISUPPORTS(DomainPolicy, nsIDomainPolicy)
@@ -146,21 +147,20 @@ DomainPolicy::ApplyClone(const DomainPol
CopyURIs(aClone->superBlacklist(), mSuperBlacklist);
CopyURIs(aClone->superWhitelist(), mSuperWhitelist);
}
static already_AddRefed<nsIURI>
GetCanonicalClone(nsIURI* aURI)
{
nsCOMPtr<nsIURI> clone;
- nsresult rv = aURI->Clone(getter_AddRefs(clone));
- NS_ENSURE_SUCCESS(rv, nullptr);
- rv = clone->SetUserPass(EmptyCString());
- NS_ENSURE_SUCCESS(rv, nullptr);
- rv = clone->SetPathQueryRef(EmptyCString());
+ nsresult rv = NS_MutateURI(aURI)
+ .SetUserPass(EmptyCString())
+ .SetPathQueryRef(EmptyCString())
+ .Finalize(clone);
NS_ENSURE_SUCCESS(rv, nullptr);
return clone.forget();
}
NS_IMPL_ISUPPORTS(DomainSet, nsIDomainSet)
NS_IMETHODIMP
DomainSet::Add(nsIURI* aDomain)
--- a/chrome/nsChromeProtocolHandler.cpp
+++ b/chrome/nsChromeProtocolHandler.cpp
@@ -72,17 +72,17 @@ nsChromeProtocolHandler::NewURI(const ns
const char *aCharset,
nsIURI *aBaseURI,
nsIURI **result)
{
// Chrome: URLs (currently) have no additional structure beyond that provided
// by standard URLs, so there is no "outer" given to CreateInstance
nsresult rv;
- nsCOMPtr<nsIURL> surl;
+ nsCOMPtr<nsIURI> surl;
nsCOMPtr<nsIURI> base(aBaseURI);
rv = NS_MutateURI(new mozilla::net::nsStandardURL::Mutator())
.Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
nsIStandardURL::URLTYPE_STANDARD,
-1, nsCString(aSpec), aCharset,
base, nullptr))
.Finalize(surl);
if (NS_FAILED(rv)) {
@@ -113,27 +113,23 @@ nsChromeProtocolHandler::NewChannel2(nsI
NS_ENSURE_ARG_POINTER(aURI);
NS_ENSURE_ARG_POINTER(aLoadInfo);
NS_PRECONDITION(aResult, "Null out param");
#ifdef DEBUG
// Check that the uri we got is already canonified
nsresult debug_rv;
- nsCOMPtr<nsIURI> debugClone;
- debug_rv = aURI->Clone(getter_AddRefs(debugClone));
+ nsCOMPtr<nsIURI> debugURL = aURI;
+ debug_rv = nsChromeRegistry::Canonify(debugURL);
if (NS_SUCCEEDED(debug_rv)) {
- nsCOMPtr<nsIURL> debugURL (do_QueryInterface(debugClone));
- debug_rv = nsChromeRegistry::Canonify(debugURL);
+ bool same;
+ debug_rv = aURI->Equals(debugURL, &same);
if (NS_SUCCEEDED(debug_rv)) {
- bool same;
- debug_rv = aURI->Equals(debugURL, &same);
- if (NS_SUCCEEDED(debug_rv)) {
- NS_ASSERTION(same, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!");
- }
+ NS_ASSERTION(same, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!");
}
}
#endif
nsCOMPtr<nsIChannel> result;
if (!nsChromeRegistry::gChromeRegistry) {
// We don't actually want this ref, we just want the service to
--- a/chrome/nsChromeRegistry.cpp
+++ b/chrome/nsChromeRegistry.cpp
@@ -26,16 +26,17 @@
#include "nsIScriptError.h"
#include "nsIWindowMediator.h"
#include "nsIPrefService.h"
#include "mozilla/Preferences.h"
#include "mozilla/Printf.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"
#include "mozilla/dom/Location.h"
+#include "nsIURIMutator.h"
#include "unicode/uloc.h"
nsChromeRegistry* nsChromeRegistry::gChromeRegistry;
// DO NOT use namespace mozilla; it'll break due to a naming conflict between
// mozilla::TextRange and a TextRange in OSX headers.
using mozilla::StyleSheet;
@@ -147,17 +148,17 @@ nsChromeRegistry::Init()
gChromeRegistry = this;
mInitialized = true;
return NS_OK;
}
nsresult
-nsChromeRegistry::GetProviderAndPath(nsIURL* aChromeURL,
+nsChromeRegistry::GetProviderAndPath(nsIURI* aChromeURL,
nsACString& aProvider, nsACString& aPath)
{
nsresult rv;
#ifdef DEBUG
bool isChrome;
aChromeURL->SchemeIs("chrome", &isChrome);
NS_ASSERTION(isChrome, "Non-chrome URI?");
@@ -194,17 +195,17 @@ nsChromeRegistry::GetProviderAndPath(nsI
}
aProvider.Assign(path.get() + 1, slash);
return NS_OK;
}
nsresult
-nsChromeRegistry::Canonify(nsIURL* aChromeURL)
+nsChromeRegistry::Canonify(nsCOMPtr<nsIURI>& aChromeURL)
{
NS_NAMED_LITERAL_CSTRING(kSlash, "/");
nsresult rv;
nsAutoCString provider, path;
rv = GetProviderAndPath(aChromeURL, provider, path);
NS_ENSURE_SUCCESS(rv, rv);
@@ -223,17 +224,19 @@ nsChromeRegistry::Canonify(nsIURL* aChro
path.AppendLiteral(".dtd");
}
else if (provider.EqualsLiteral("skin")) {
path.AppendLiteral(".css");
}
else {
return NS_ERROR_INVALID_ARG;
}
- aChromeURL->SetPathQueryRef(path);
+ return NS_MutateURI(aChromeURL)
+ .SetPathQueryRef(path)
+ .Finalize(aChromeURL);
}
else {
// prevent directory traversals ("..")
// path is already unescaped once, but uris can get unescaped twice
const char* pos = path.BeginReading();
const char* end = path.EndReading();
// Must start with [a-zA-Z0-9].
if (!('a' <= *pos && *pos <= 'z') &&
--- a/chrome/nsChromeRegistry.h
+++ b/chrome/nsChromeRegistry.h
@@ -65,17 +65,20 @@ public:
nsChromeRegistry() : mInitialized(false) { }
virtual nsresult Init();
static already_AddRefed<nsIChromeRegistry> GetService();
static nsChromeRegistry* gChromeRegistry;
- static nsresult Canonify(nsIURL* aChromeURL);
+ // This method can change its parameter, so due to thread safety issues
+ // it should only be called for nsCOMPtr<nsIURI> that is on the stack,
+ // unless you know what you are doing.
+ static nsresult Canonify(nsCOMPtr<nsIURI>& aChromeURL);
protected:
virtual ~nsChromeRegistry();
void FlushSkinCaches();
void FlushAllCaches();
static void LogMessage(const char* aMsg, ...)
@@ -86,17 +89,17 @@ protected:
virtual nsIURI* GetBaseURIFromPackage(const nsCString& aPackage,
const nsCString& aProvider,
const nsCString& aPath) = 0;
virtual nsresult GetFlagsFromPackage(const nsCString& aPackage,
uint32_t* aFlags) = 0;
static nsresult RefreshWindow(nsPIDOMWindowOuter* aWindow);
- static nsresult GetProviderAndPath(nsIURL* aChromeURL,
+ static nsresult GetProviderAndPath(nsIURI* aChromeURL,
nsACString& aProvider, nsACString& aPath);
bool GetDirectionForLocale(const nsACString& aLocale);
void SanitizeForBCP47(nsACString& aLocale);
public:
static already_AddRefed<nsChromeRegistry> GetSingleton();
--- a/dom/base/FormData.cpp
+++ b/dom/base/FormData.cpp
@@ -96,17 +96,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
// -------------------------------------------------------------------------
// HTMLFormSubmission
nsresult
FormData::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream,
- int64_t* aPostDataStreamLength)
+ int64_t* aPostDataStreamLength,
+ nsCOMPtr<nsIURI>& aOutURI)
{
NS_NOTREACHED("Shouldn't call FormData::GetEncodedSubmission");
return NS_OK;
}
void
FormData::Append(const nsAString& aName, const nsAString& aValue,
ErrorResult& aRv)
--- a/dom/base/FormData.h
+++ b/dom/base/FormData.h
@@ -102,17 +102,17 @@ public:
const nsAString& GetKeyAtIndex(uint32_t aIndex) const;
const OwningBlobOrDirectoryOrUSVString& GetValueAtIndex(uint32_t aIndex) const;
// HTMLFormSubmission
virtual nsresult
GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
- int64_t* aPostDataStreamLength) override;
+ int64_t* aPostDataStreamLength, nsCOMPtr<nsIURI>& aOutURI) override;
virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue) override
{
FormDataTuple* data = mFormData.AppendElement();
SetNameValuePair(data, aName, aValue);
return NS_OK;
}
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -268,16 +268,17 @@
#include "mozilla/DocLoadingTimelineMarker.h"
#include "nsISpeculativeConnect.h"
#include "mozilla/MediaManager.h"
#include "nsIURIClassifier.h"
+#include "nsIURIMutator.h"
#include "mozilla/DocumentStyleRootIterator.h"
#include "mozilla/ServoRestyleManager.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsHTMLTags.h"
using namespace mozilla;
using namespace mozilla::dom;
@@ -9116,32 +9117,38 @@ nsDocument::MaybePreLoadImage(nsIURI* ur
if (NS_SUCCEEDED(rv)) {
mPreloadingImages.Put(uri, request.forget());
}
}
void
nsDocument::MaybePreconnect(nsIURI* aOrigURI, mozilla::CORSMode aCORSMode)
{
- nsCOMPtr<nsIURI> uri;
- if (NS_FAILED(aOrigURI->Clone(getter_AddRefs(uri)))) {
+ NS_MutateURI mutator(aOrigURI);
+ if (NS_FAILED(mutator.GetStatus())) {
return;
}
// The URI created here is used in 2 contexts. One is nsISpeculativeConnect
// which ignores the path and uses only the origin. The other is for the
// document mPreloadedPreconnects de-duplication hash. Anonymous vs
// non-Anonymous preconnects create different connections on the wire and
// therefore should not be considred duplicates of each other and we
// normalize the path before putting it in the hash to accomplish that.
if (aCORSMode == CORS_ANONYMOUS) {
- uri->SetPathQueryRef(NS_LITERAL_CSTRING("/anonymous"));
+ mutator.SetPathQueryRef(NS_LITERAL_CSTRING("/anonymous"));
} else {
- uri->SetPathQueryRef(NS_LITERAL_CSTRING("/"));
+ mutator.SetPathQueryRef(NS_LITERAL_CSTRING("/"));
+ }
+
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = mutator.Finalize(uri);
+ if (NS_FAILED(rv)) {
+ return;
}
auto entry = mPreloadedPreconnects.LookupForAdd(uri);
if (entry) {
return; // we found an existing entry
}
entry.OrInsert([] () { return true; });
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -141,16 +141,17 @@
#include "nsIControllers.h"
#include "nsIControllerContext.h"
#include "nsGlobalWindowCommands.h"
#include "nsQueryObject.h"
#include "nsContentUtils.h"
#include "nsCSSProps.h"
#include "nsIDOMFileList.h"
#include "nsIURIFixup.h"
+#include "nsIURIMutator.h"
#ifndef DEBUG
#include "nsIAppStartup.h"
#include "nsToolkitCompsCID.h"
#endif
#include "nsCDefaultURIFixup.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventStateManager.h"
#include "nsIObserverService.h"
@@ -5788,18 +5789,21 @@ nsGlobalWindowOuter::PostMessageMozOuter
// "*" indicates no specific origin is required.
else if (!aTargetOrigin.EqualsASCII("*")) {
nsCOMPtr<nsIURI> originURI;
if (NS_FAILED(NS_NewURI(getter_AddRefs(originURI), aTargetOrigin))) {
aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
- if (NS_FAILED(originURI->SetUserPass(EmptyCString())) ||
- NS_FAILED(originURI->SetPathQueryRef(EmptyCString()))) {
+ nsresult rv = NS_MutateURI(originURI)
+ .SetUserPass(EmptyCString())
+ .SetPathQueryRef(EmptyCString())
+ .Finalize(originURI);
+ if (NS_FAILED(rv)) {
return;
}
OriginAttributes attrs = aSubjectPrincipal.OriginAttributesRef();
if (aSubjectPrincipal.GetIsSystemPrincipal()) {
auto principal = BasePrincipal::Cast(GetPrincipal());
if (attrs != principal->OriginAttributesRef()) {
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -772,17 +772,18 @@ HTMLFormElement::SubmitSubmission(HTMLFo
AutoHandlingUserInputStatePusher userInpStatePusher(
mSubmitInitiatedFromUserInput,
nullptr, doc);
nsCOMPtr<nsIInputStream> postDataStream;
int64_t postDataStreamLength = -1;
rv = aFormSubmission->GetEncodedSubmission(actionURI,
getter_AddRefs(postDataStream),
- &postDataStreamLength);
+ &postDataStreamLength,
+ actionURI);
NS_ENSURE_SUBMIT_SUCCESS(rv);
rv = linkHandler->OnLinkClickSync(this, actionURI,
target.get(),
VoidString(),
postDataStream, postDataStreamLength,
nullptr, false,
getter_AddRefs(docShell),
--- a/dom/html/HTMLFormSubmission.cpp
+++ b/dom/html/HTMLFormSubmission.cpp
@@ -14,16 +14,17 @@
#include "nsIFormControl.h"
#include "nsError.h"
#include "nsGenericHTMLElement.h"
#include "nsAttrValueInlines.h"
#include "nsIFile.h"
#include "nsDirectoryServiceDefs.h"
#include "nsStringStream.h"
#include "nsIURI.h"
+#include "nsIURIMutator.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
#include "nsLinebreakConverter.h"
#include "nsEscape.h"
#include "nsUnicharUtils.h"
#include "nsIMultiplexInputStream.h"
#include "nsIMIMEInputStream.h"
#include "nsIMIMEService.h"
@@ -108,17 +109,17 @@ public:
virtual nsresult
AddNameBlobOrNullPair(const nsAString& aName, Blob* aBlob) override;
virtual nsresult
AddNameDirectoryPair(const nsAString& aName, Directory* aDirectory) override;
virtual nsresult
GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
- int64_t* aPostDataStreamLength) override;
+ int64_t* aPostDataStreamLength, nsCOMPtr<nsIURI>& aOutURI) override;
protected:
/**
* URL encode a Unicode string by encoding it to bytes, converting linebreaks
* properly, and then escaping many bytes as %xx.
*
* @param aStr the string to encode
@@ -263,19 +264,21 @@ HandleMailtoSubject(nsCString& aPath)
aPath.Append(subjectStrEscaped);
}
}
nsresult
FSURLEncoded::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream,
- int64_t* aPostDataStreamLength)
+ int64_t* aPostDataStreamLength,
+ nsCOMPtr<nsIURI>& aOutURI)
{
nsresult rv = NS_OK;
+ aOutURI = aURI;
*aPostDataStream = nullptr;
*aPostDataStreamLength = -1;
if (mMethod == NS_FORM_METHOD_POST) {
bool isMailto = false;
aURI->SchemeIs("mailto", &isMailto);
@@ -290,18 +293,19 @@ FSURLEncoded::GetEncodedSubmission(nsIUR
// Append the body to and force-plain-text args to the mailto line
nsAutoCString escapedBody;
if (NS_WARN_IF(!NS_Escape(mQueryString, escapedBody, url_XAlphas))) {
return NS_ERROR_OUT_OF_MEMORY;
}
path += NS_LITERAL_CSTRING("&force-plain-text=Y&body=") + escapedBody;
- rv = aURI->SetPathQueryRef(path);
-
+ return NS_MutateURI(aURI)
+ .SetPathQueryRef(path)
+ .Finalize(aOutURI);
} else {
nsCOMPtr<nsIInputStream> dataStream;
// XXX We *really* need to either get the string to disown its data (and
// not destroy it), or make a string input stream that owns the CString
// that is passed to it. Right now this operation does a copy.
rv = NS_NewCStringInputStream(getter_AddRefs(dataStream), mQueryString);
NS_ENSURE_SUCCESS(rv, rv);
@@ -326,17 +330,19 @@ FSURLEncoded::GetEncodedSubmission(nsIUR
rv = aURI->SchemeIs("javascript", &schemeIsJavaScript);
NS_ENSURE_SUCCESS(rv, rv);
if (schemeIsJavaScript) {
return NS_OK;
}
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
if (url) {
- url->SetQuery(mQueryString);
+ rv = NS_MutateURI(aURI)
+ .SetQuery(mQueryString)
+ .Finalize(aOutURI);
}
else {
nsAutoCString path;
rv = aURI->GetPathQueryRef(path);
NS_ENSURE_SUCCESS(rv, rv);
// Bug 42616: Trim off named anchor and save it to add later
int32_t namedAnchorPos = path.FindChar('#');
nsAutoCString namedAnchor;
@@ -351,17 +357,19 @@ FSURLEncoded::GetEncodedSubmission(nsIUR
if (kNotFound != queryStart) {
path.Truncate(queryStart);
}
path.Append('?');
// Bug 42616: Add named anchor to end after query string
path.Append(mQueryString + namedAnchor);
- aURI->SetPathQueryRef(path);
+ rv = NS_MutateURI(aURI)
+ .SetPathQueryRef(path)
+ .Finalize(aOutURI);
}
}
return rv;
}
// i18n helper routines
nsresult
@@ -616,19 +624,21 @@ FSMultipartFormData::AddDataChunk(const
// CRLF after file
mPostDataChunk.AppendLiteral(CRLF);
}
nsresult
FSMultipartFormData::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream,
- int64_t* aPostDataStreamLength)
+ int64_t* aPostDataStreamLength,
+ nsCOMPtr<nsIURI>& aOutURI)
{
nsresult rv;
+ aOutURI = aURI;
// Make header
nsCOMPtr<nsIMIMEInputStream> mimeStream
= do_CreateInstance("@mozilla.org/network/mime-input-stream;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString contentType;
GetContentType(contentType);
@@ -681,17 +691,17 @@ public:
virtual nsresult
AddNameBlobOrNullPair(const nsAString& aName, Blob* aBlob) override;
virtual nsresult
AddNameDirectoryPair(const nsAString& aName, Directory* aDirectory) override;
virtual nsresult
GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
- int64_t* aPostDataStreaLength) override;
+ int64_t* aPostDataStreaLength, nsCOMPtr<nsIURI>& aOutURI) override;
private:
nsString mBody;
};
nsresult
FSTextPlain::AddNameValuePair(const nsAString& aName, const nsAString& aValue)
{
@@ -721,19 +731,21 @@ FSTextPlain::AddNameDirectoryPair(const
RetrieveDirectoryName(aDirectory, dirname);
AddNameValuePair(aName, dirname);
return NS_OK;
}
nsresult
FSTextPlain::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream,
- int64_t* aPostDataStreamLength)
+ int64_t* aPostDataStreamLength,
+ nsCOMPtr<nsIURI>& aOutURI)
{
nsresult rv = NS_OK;
+ aOutURI = aURI;
*aPostDataStream = nullptr;
*aPostDataStreamLength = -1;
// XXX HACK We are using the standard URL mechanism to give the body to the
// mailer instead of passing the post data stream to it, since that sounds
// hard.
bool isMailto = false;
@@ -749,18 +761,19 @@ FSTextPlain::GetEncodedSubmission(nsIURI
nsAutoCString escapedBody;
if (NS_WARN_IF(!NS_Escape(NS_ConvertUTF16toUTF8(mBody), escapedBody,
url_XAlphas))) {
return NS_ERROR_OUT_OF_MEMORY;
}
path += NS_LITERAL_CSTRING("&force-plain-text=Y&body=") + escapedBody;
- rv = aURI->SetPathQueryRef(path);
-
+ rv = NS_MutateURI(aURI)
+ .SetPathQueryRef(path)
+ .Finalize(aOutURI);
} else {
// Create data stream.
// We do want to send the data through the charset encoder and we want to
// normalize linebreaks to use the "standard net" format (\r\n), but we
// don't want to perform any other encoding. This means that names and
// values which contains '=' or newlines are potentially ambigiously
// encoded, but that how text/plain is specced.
nsCString cbody;
--- a/dom/html/HTMLFormSubmission.h
+++ b/dom/html/HTMLFormSubmission.h
@@ -77,23 +77,25 @@ public:
*/
virtual nsresult AddNameDirectoryPair(const nsAString& aName,
Directory* aDirectory) = 0;
/**
* Given a URI and the current submission, create the final URI and data
* stream that will be submitted. Subclasses *must* implement this.
*
- * @param aURI the URI being submitted to [INOUT]
+ * @param aURI the URI being submitted to [IN]
* @param aPostDataStream a data stream for POST data [OUT]
* @param aPostDataStreamLength a data stream for POST data length [OUT]
+ * @param aOutURI the resulting URI. May be the same as aURI [OUT]
*/
virtual nsresult
GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
- int64_t* aPostDataStreamLength) = 0;
+ int64_t* aPostDataStreamLength,
+ nsCOMPtr<nsIURI>& aOutURI) = 0;
/**
* Get the charset that will be used for submission.
*/
void GetCharset(nsACString& aCharset) { mEncoding->Name(aCharset); }
Element* GetOriginatingElement() const
{
@@ -163,17 +165,17 @@ public:
virtual nsresult
AddNameBlobOrNullPair(const nsAString& aName, Blob* aBlob) override;
virtual nsresult
AddNameDirectoryPair(const nsAString& aName, Directory* aDirectory) override;
virtual nsresult
GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
- int64_t* aPostDataStreamLength) override;
+ int64_t* aPostDataStreamLength, nsCOMPtr<nsIURI>& aOutURI) override;
void GetContentType(nsACString& aContentType)
{
aContentType =
NS_LITERAL_CSTRING("multipart/form-data; boundary=") + mBoundary;
}
nsIInputStream* GetSubmissionBody(uint64_t* aContentLength);
--- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -620,17 +620,17 @@ nsWebBrowserPersist::SerializeNextFile()
}
// Make a URI to save the data to.
nsCOMPtr<nsIURI> fileAsURI;
rv = data->mDataPath->Clone(getter_AddRefs(fileAsURI));
if (NS_WARN_IF(NS_FAILED(rv))) {
break;
}
- rv = AppendPathToURI(fileAsURI, data->mFilename);
+ rv = AppendPathToURI(fileAsURI, data->mFilename, fileAsURI);
if (NS_WARN_IF(NS_FAILED(rv))) {
break;
}
// The Referrer Policy doesn't matter here since the referrer is
// nullptr.
rv = SaveURIInternal(uri, nullptr, nullptr,
mozilla::net::RP_Unset, nullptr, nullptr,
@@ -1286,36 +1286,37 @@ nsWebBrowserPersist::GetLocalFileFromURI
return rv;
}
file.forget(aLocalFile);
return NS_OK;
}
/* static */ nsresult
-nsWebBrowserPersist::AppendPathToURI(nsIURI *aURI, const nsAString & aPath)
+nsWebBrowserPersist::AppendPathToURI(nsIURI *aURI, const nsAString & aPath, nsCOMPtr<nsIURI>& aOutURI)
{
NS_ENSURE_ARG_POINTER(aURI);
nsAutoCString newPath;
nsresult rv = aURI->GetPathQueryRef(newPath);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
// Append a forward slash if necessary
int32_t len = newPath.Length();
if (len > 0 && newPath.CharAt(len - 1) != '/')
{
newPath.Append('/');
}
// Store the path back on the URI
AppendUTF16toUTF8(aPath, newPath);
- aURI->SetPathQueryRef(newPath);
-
- return NS_OK;
+
+ return NS_MutateURI(aURI)
+ .SetPathQueryRef(newPath)
+ .Finalize(aOutURI);
}
nsresult nsWebBrowserPersist::SaveURIInternal(
nsIURI *aURI, nsISupports *aCacheKey, nsIURI *aReferrer,
uint32_t aReferrerPolicy, nsIInputStream *aPostData,
const char *aExtraHeaders, nsIURI *aFile,
bool aCalcFileExt, bool aIsPrivate)
{
@@ -2562,17 +2563,17 @@ nsWebBrowserPersist::URIData::GetLocalUR
nsresult rv;
nsCOMPtr<nsIURI> fileAsURI;
if (mFile) {
rv = mFile->Clone(getter_AddRefs(fileAsURI));
NS_ENSURE_SUCCESS(rv, rv);
} else {
rv = mDataPath->Clone(getter_AddRefs(fileAsURI));
NS_ENSURE_SUCCESS(rv, rv);
- rv = AppendPathToURI(fileAsURI, mFilename);
+ rv = AppendPathToURI(fileAsURI, mFilename, fileAsURI);
NS_ENSURE_SUCCESS(rv, rv);
}
// remove username/password if present
fileAsURI->SetUserPass(EmptyCString());
// reset node attribute
// Use relative or absolute links
@@ -2685,28 +2686,28 @@ nsWebBrowserPersist::SaveSubframeContent
nsString filenameWithExt = aData->mFilename;
filenameWithExt.Append(aData->mSubFrameExt);
// Work out the path for the subframe
nsCOMPtr<nsIURI> frameURI;
rv = mCurrentDataPath->Clone(getter_AddRefs(frameURI));
NS_ENSURE_SUCCESS(rv, rv);
- rv = AppendPathToURI(frameURI, filenameWithExt);
+ rv = AppendPathToURI(frameURI, filenameWithExt, frameURI);
NS_ENSURE_SUCCESS(rv, rv);
// Work out the path for the subframe data
nsCOMPtr<nsIURI> frameDataURI;
rv = mCurrentDataPath->Clone(getter_AddRefs(frameDataURI));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString newFrameDataPath(aData->mFilename);
// Append _data
newFrameDataPath.AppendLiteral("_data");
- rv = AppendPathToURI(frameDataURI, newFrameDataPath);
+ rv = AppendPathToURI(frameDataURI, newFrameDataPath, frameDataURI);
NS_ENSURE_SUCCESS(rv, rv);
// Make frame document & data path conformant and unique
nsCOMPtr<nsIURI> out;
rv = CalculateUniqueFilename(frameURI, out);
NS_ENSURE_SUCCESS(rv, rv);
frameURI = out;
--- a/dom/webbrowserpersist/nsWebBrowserPersist.h
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.h
@@ -86,17 +86,17 @@ private:
friend class OnWalk;
friend class OnWrite;
nsresult SaveDocumentDeferred(mozilla::UniquePtr<WalkData>&& aData);
void Cleanup();
void CleanupLocalFiles();
nsresult GetValidURIFromObject(nsISupports *aObject, nsIURI **aURI) const;
static nsresult GetLocalFileFromURI(nsIURI *aURI, nsIFile **aLocalFile);
- static nsresult AppendPathToURI(nsIURI *aURI, const nsAString & aPath);
+ static nsresult AppendPathToURI(nsIURI *aURI, const nsAString & aPath, nsCOMPtr<nsIURI>& aOutURI);
nsresult MakeAndStoreLocalFilenameInURIMap(
nsIURI *aURI, bool aNeedsPersisting, URIData **aData);
nsresult MakeOutputStream(
nsIURI *aFile, nsIOutputStream **aOutputStream);
nsresult MakeOutputStreamFromFile(
nsIFile *aFile, nsIOutputStream **aOutputStream);
nsresult MakeOutputStreamFromURI(nsIURI *aURI, nsIOutputStream **aOutStream);
nsresult CreateChannelFromURI(nsIURI *aURI, nsIChannel **aChannel);
--- a/netwerk/protocol/ftp/nsFTPChannel.h
+++ b/netwerk/protocol/ftp/nsFTPChannel.h
@@ -42,16 +42,21 @@ public:
, mStartPos(0)
, mResumeRequested(false)
, mLastModifiedTime(0)
, mForcePending(false)
{
SetURI(uri);
}
+ void UpdateURI(nsIURI *aURI) {
+ MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(), "Not thread-safe.");
+ mURI = aURI;
+ }
+
nsIProxyInfo *ProxyInfo() {
return mProxyInfo;
}
void SetProxyInfo(nsIProxyInfo *pi)
{
mProxyInfo = pi;
}
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -35,16 +35,17 @@
#include "nsICancelable.h"
#include "nsIOutputStream.h"
#include "nsIPrompt.h"
#include "nsIProtocolHandler.h"
#include "nsIProxyInfo.h"
#include "nsIRunnable.h"
#include "nsISocketTransportService.h"
#include "nsIURI.h"
+#include "nsIURIMutator.h"
#include "nsILoadInfo.h"
#include "NullPrincipal.h"
#include "nsIAuthPrompt2.h"
#include "nsIFTPChannelParentInternal.h"
using namespace mozilla;
using namespace mozilla::net;
@@ -1640,21 +1641,29 @@ nsFtpState::Init(nsFtpChannel *channel)
} else {
rv = mChannel->URI()->GetPathQueryRef(path);
}
if (NS_FAILED(rv))
return rv;
removeParamsFromPath(path);
+ nsCOMPtr<nsIURI> outURI;
// FTP parameters such as type=i are ignored
if (url) {
- url->SetFilePath(path);
+ rv = NS_MutateURI(url)
+ .SetFilePath(path)
+ .Finalize(outURI);
} else {
- mChannel->URI()->SetPathQueryRef(path);
+ rv = NS_MutateURI(mChannel->URI())
+ .SetPathQueryRef(path)
+ .Finalize(outURI);
+ }
+ if (NS_SUCCEEDED(rv)) {
+ mChannel->UpdateURI(outURI);
}
// Skip leading slash
char *fwdPtr = path.BeginWriting();
if (!fwdPtr)
return NS_ERROR_OUT_OF_MEMORY;
if (*fwdPtr == '/')
fwdPtr++;
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1788,17 +1788,19 @@ HttpBaseChannel::SetReferrerWithPolicy(n
rv = mURI->CloneIgnoringRef(getter_AddRefs(mURIclone));
if (NS_FAILED(rv)) return rv;
clone = mURIclone;
currentHost = referrerHost;
}
// strip away any userpass; we don't want to be giving out passwords ;-)
// This is required by Referrer Policy stripping algorithm.
- rv = clone->SetUserPass(EmptyCString());
+ rv = NS_MutateURI(clone)
+ .SetUserPass(EmptyCString())
+ .Finalize(clone);
if (NS_FAILED(rv)) return rv;
// 0: full URI
// 1: scheme+host+port+path
// 2: scheme+host+port
int userReferrerTrimmingPolicy = gHttpHandler->ReferrerTrimmingPolicy();
int userReferrerXOriginTrimmingPolicy =
gHttpHandler->ReferrerXOriginTrimmingPolicy();
@@ -1866,31 +1868,34 @@ HttpBaseChannel::SetReferrerWithPolicy(n
switch (userReferrerTrimmingPolicy) {
case 1: { // scheme+host+port+path
nsCOMPtr<nsIURL> url(do_QueryInterface(clone));
if (url) {
nsAutoCString path;
rv = url->GetFilePath(path);
if (NS_FAILED(rv)) return rv;
spec.Append(path);
- rv = url->SetQuery(EmptyCString());
- if (NS_FAILED(rv)) return rv;
- rv = url->SetRef(EmptyCString());
+ rv = NS_MutateURI(url)
+ .SetQuery(EmptyCString())
+ .SetRef(EmptyCString())
+ .Finalize(clone);
if (NS_FAILED(rv)) return rv;
break;
}
// No URL, so fall through to truncating the path and any query/ref off
// as well.
}
MOZ_FALLTHROUGH;
default: // (Pref limited to [0,2] enforced by clamp, MOZ_CRASH overkill.)
case 2: // scheme+host+port+/
spec.AppendLiteral("/");
// This nukes any query/ref present as well in the case of nsStandardURL
- rv = clone->SetPathQueryRef(EmptyCString());
+ rv = NS_MutateURI(clone)
+ .SetPathQueryRef(EmptyCString())
+ .Finalize(clone);
if (NS_FAILED(rv)) return rv;
break;
}
} else {
// use the full URI
rv = clone->GetAsciiSpec(spec);
if (NS_FAILED(rv)) return rv;
}
--- a/netwerk/streamconv/converters/nsIndexedToHTML.cpp
+++ b/netwerk/streamconv/converters/nsIndexedToHTML.cpp
@@ -8,28 +8,30 @@
#include "DateTimeFormat.h"
#include "mozilla/Encoding.h"
#include "mozilla/intl/LocaleService.h"
#include "nsNetUtil.h"
#include "netCore.h"
#include "nsStringStream.h"
#include "nsIFile.h"
#include "nsIFileURL.h"
+#include "nsIURIMutator.h"
#include "nsEscape.h"
#include "nsIDirIndex.h"
#include "nsURLHelper.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIPrefLocalizedString.h"
#include "nsIStringBundle.h"
#include "nsITextToSubURI.h"
#include "nsNativeCharsetUtils.h"
#include "nsString.h"
#include <algorithm>
#include "nsIChannel.h"
+#include "mozilla/Unused.h"
using mozilla::intl::LocaleService;
NS_IMPL_ISUPPORTS(nsIndexedToHTML,
nsIDirIndexListener,
nsIStreamConverter,
nsIRequestObserver,
nsIStreamListener)
@@ -244,17 +246,19 @@ nsIndexedToHTML::DoOnStartRequest(nsIReq
// default behavior for other protocols is to assume the channel's
// URL references a directory ending in '/' -- fixup if necessary.
nsAutoCString path;
rv = uri->GetPathQueryRef(path);
if (NS_FAILED(rv)) return rv;
if (baseUri.Last() != '/') {
baseUri.Append('/');
path.Append('/');
- uri->SetPathQueryRef(path);
+ mozilla::Unused << NS_MutateURI(uri)
+ .SetPathQueryRef(path)
+ .Finalize(uri);
}
if (!path.EqualsLiteral("/")) {
rv = uri->Resolve(NS_LITERAL_CSTRING(".."), parentStr);
if (NS_FAILED(rv)) return rv;
}
}
buffer.AppendLiteral("<style type=\"text/css\">\n"
--- a/netwerk/test/unit/test_URIs.js
+++ b/netwerk/test/unit/test_URIs.js
@@ -497,40 +497,40 @@ function do_test_mutate_ref(aTest, aSuff
if (!(testURI instanceof Ci.nsIJARURI)) {
// Now try setting .pathQueryRef directly (including suffix) and then clearing .ref
// (same as above, but with now with .pathQueryRef instead of .spec)
testURI = NetUtil.newURI(aTest.spec);
var pathWithSuffix = aTest.pathQueryRef + aSuffix;
do_info("testing that setting path to " +
pathWithSuffix + " and then clearing ref does what we expect");
- testURI.pathQueryRef = pathWithSuffix;
+ testURI = testURI.mutate().setPathQueryRef(pathWithSuffix).finalize();
testURI.ref = "";
do_check_uri_eq(testURI, refURIWithoutSuffix);
do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
// Also: make sure that clearing .pathQueryRef also clears .ref
- testURI.pathQueryRef = pathWithSuffix;
+ testURI = testURI.mutate().setPathQueryRef(pathWithSuffix).finalize();
do_info("testing that clearing path from " +
pathWithSuffix + " also clears .ref");
- testURI.pathQueryRef = "";
+ testURI = testURI.mutate().setPathQueryRef("").finalize();
Assert.equal(testURI.ref, "");
}
}
}
// Tests that normally-mutable properties can't be modified on
// special URIs that are known to be immutable.
function do_test_immutable(aTest) {
Assert.ok(aTest.immutable);
var URI = NetUtil.newURI(aTest.spec);
// All the non-readonly attributes on nsIURI.idl:
var propertiesToCheck = ["spec", "scheme", "userPass", "username", "password",
- "host", "port", "pathQueryRef", "query", "ref"];
+ "host", "port", "query", "ref"];
propertiesToCheck.forEach(function(aProperty) {
var threw = false;
try {
URI[aProperty] = "anothervalue";
} catch(e) {
threw = true;
}
--- a/netwerk/test/unit/test_URIs2.js
+++ b/netwerk/test/unit/test_URIs2.js
@@ -598,40 +598,40 @@ function do_test_mutate_ref(aTest, aSuff
if (!(testURI instanceof Ci.nsIJARURI)) {
// Now try setting .pathQueryRef directly (including suffix) and then clearing .ref
// (same as above, but with now with .pathQueryRef instead of .spec)
testURI = NetUtil.newURI(aTest.spec);
var pathWithSuffix = aTest.pathQueryRef + aSuffix;
do_info("testing that setting path to " +
pathWithSuffix + " and then clearing ref does what we expect");
- testURI.pathQueryRef = pathWithSuffix;
+ testURI = testURI.mutate().setPathQueryRef(pathWithSuffix).finalize();
testURI.ref = "";
do_check_uri_eq(testURI, refURIWithoutSuffix);
do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
// Also: make sure that clearing .pathQueryRef also clears .ref
- testURI.pathQueryRef = pathWithSuffix;
+ testURI = testURI.mutate().setPathQueryRef(pathWithSuffix).finalize();
do_info("testing that clearing path from " +
pathWithSuffix + " also clears .ref");
- testURI.pathQueryRef = "";
+ testURI = testURI.mutate().setPathQueryRef("").finalize();
Assert.equal(testURI.ref, "");
}
}
}
// Tests that normally-mutable properties can't be modified on
// special URIs that are known to be immutable.
function do_test_immutable(aTest) {
Assert.ok(aTest.immutable);
var URI = NetUtil.newURI(aTest.spec);
// All the non-readonly attributes on nsIURI.idl:
var propertiesToCheck = ["scheme", "userPass", "username", "password",
- "host", "port", "pathQueryRef", "query", "ref"];
+ "host", "port", "query", "ref"];
propertiesToCheck.forEach(function(aProperty) {
var threw = false;
try {
URI[aProperty] = "anothervalue";
} catch(e) {
threw = true;
}
--- a/netwerk/test/unit/test_standardurl.js
+++ b/netwerk/test/unit/test_standardurl.js
@@ -50,18 +50,18 @@ add_test(function test_setEmptyPath()
["http://example.com/a", "http://example.com/tests/dom/tests"],
["http://example.com:80/a", "http://example.com/tests/dom/tests"],
].map(pairToURLs);
for (var [provided, target] of pairs)
{
symmetricEquality(false, target, provided);
- provided.pathQueryRef = "";
- target.pathQueryRef = "";
+ provided = provided.mutate().setPathQueryRef("").finalize();
+ target = target.mutate().setPathQueryRef("").finalize();
Assert.equal(provided.spec, target.spec);
symmetricEquality(true, target, provided);
}
run_next_test();
});
add_test(function test_setQuery()
@@ -297,27 +297,28 @@ add_test(function test_hugeStringThrows(
{
let prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService);
let maxLen = prefs.getIntPref("network.standard-url.max-length");
let url = stringToURL("http://test:test@example.com");
let hugeString = new Array(maxLen + 1).fill("a").join("");
let properties = ["scheme", "userPass", "username",
- "password", "host", "pathQueryRef", "ref",
+ "password", "host", "ref",
"query", "filePath"];
for (let prop of properties) {
Assert.throws(() => url[prop] = hugeString,
/NS_ERROR_MALFORMED_URI/,
`Passing a huge string to "${prop}" should throw`);
}
let setters = [
{ method: "setSpec", qi: Ci.nsIURIMutator },
{ method: "setHostPort", qi: Ci.nsIURIMutator },
+ { method: "setPathQueryRef", qi: Ci.nsIURIMutator },
{ method: "setFileName", qi: Ci.nsIURLMutator },
{ method: "setFileExtension", qi: Ci.nsIURLMutator },
{ method: "setFileBaseName", qi: Ci.nsIURLMutator },
];
for (let prop of setters) {
Assert.throws(() => url = url.mutate().QueryInterface(prop.qi)[prop.method](hugeString).finalize(),
/NS_ERROR_MALFORMED_URI/,
--- a/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js
@@ -309,18 +309,19 @@ function run_test_invalidarg() {
function run_test_provider() {
restartManager();
const provider = new TestProvider(Components.results.NS_ERROR_NOT_AVAILABLE);
AddonManagerPrivate.registerProvider(provider);
check_mapping(provider.uri, provider.id);
- let u2 = provider.uri.clone();
- u2.pathQueryRef = "notmapped";
+ let u2 = provider.uri.mutate()
+ .setPathQueryRef("notmapped")
+ .finalize();
Assert.equal(AddonManager.mapURIToAddonID(u2), null);
AddonManagerPrivate.unregisterProvider(provider);
run_test_provider_nomap();
}
// Tests that custom providers are correctly handled, even not implementing