--- a/browser/base/content/browser-safebrowsing.js
+++ b/browser/base/content/browser-safebrowsing.js
@@ -53,16 +53,18 @@ var gSafeBrowsing = {
*/
getReportURL(name, info) {
let reportInfo = info;
if (!reportInfo) {
let pageUri = gBrowser.currentURI.clone();
// Remove the query to avoid including potentially sensitive data
if (pageUri instanceof Ci.nsIURL) {
- pageUri.query = "";
+ pageUri = pageUri.mutate()
+ .setQuery("")
+ .finalize();
}
reportInfo = { uri: pageUri.asciiSpec };
}
return SafeBrowsing.getReportURL(name, reportInfo);
}
};
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -103,17 +103,19 @@ function getSiteBlockedErrorDetails(docS
QueryInterface(Ci.nsIClassifiedChannel);
if (classifiedChannel) {
let httpChannel = docShell.failedChannel.QueryInterface(Ci.nsIHttpChannel);
let reportUri = httpChannel.URI.clone();
// Remove the query to avoid leaking sensitive data
if (reportUri instanceof Ci.nsIURL) {
- reportUri.query = "";
+ reportUri = reportUri.mutate()
+ .setQuery("")
+ .finalize();
}
blockedInfo = { list: classifiedChannel.matchedList,
provider: classifiedChannel.matchedProvider,
uri: reportUri.asciiSpec };
}
}
return blockedInfo;
--- a/dom/cache/DBAction.cpp
+++ b/dom/cache/DBAction.cpp
@@ -12,16 +12,17 @@
#include "mozilla/dom/cache/QuotaClient.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/net/nsFileProtocolHandler.h"
#include "mozIStorageConnection.h"
#include "mozIStorageService.h"
#include "mozStorageCID.h"
#include "nsIFile.h"
#include "nsIURI.h"
+#include "nsIURIMutator.h"
#include "nsIFileURL.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace dom {
namespace cache {
using mozilla::dom::quota::AssertIsOnIOThread;
@@ -192,31 +193,32 @@ OpenDBConnection(const QuotaInfo& aQuota
// Use our default file:// protocol handler directly to construct the database
// URL. This avoids any problems if a plugin registers a custom file://
// handler. If such a custom handler used javascript, then we would have a
// bad time running off the main thread here.
RefPtr<nsFileProtocolHandler> handler = new nsFileProtocolHandler();
rv = handler->Init();
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
- nsCOMPtr<nsIURI> uri;
- rv = handler->NewFileURI(dbFile, getter_AddRefs(uri));
+ nsCOMPtr<nsIURIMutator> mutator;
+ rv = handler->NewFileURIMutator(dbFile, getter_AddRefs(mutator));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
- nsCOMPtr<nsIFileURL> dbFileUrl = do_QueryInterface(uri);
- if (NS_WARN_IF(!dbFileUrl)) { return NS_ERROR_UNEXPECTED; }
+ nsCOMPtr<nsIFileURL> dbFileUrl;
nsAutoCString type;
PersistenceTypeToText(PERSISTENCE_TYPE_DEFAULT, type);
- rv = dbFileUrl->SetQuery(
+ rv = NS_MutateURI(mutator)
+ .SetQuery(
NS_LITERAL_CSTRING("persistenceType=") + type +
NS_LITERAL_CSTRING("&group=") + aQuotaInfo.mGroup +
NS_LITERAL_CSTRING("&origin=") + aQuotaInfo.mOrigin +
- NS_LITERAL_CSTRING("&cache=private"));
+ NS_LITERAL_CSTRING("&cache=private"))
+ .Finalize(dbFileUrl);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
nsCOMPtr<mozIStorageService> ss =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
if (NS_WARN_IF(!ss)) { return NS_ERROR_UNEXPECTED; }
rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(conn));
if (rv == NS_ERROR_FILE_CORRUPTED) {
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -89,16 +89,17 @@
#include "nsIPrincipal.h"
#include "nsIScriptSecurityManager.h"
#include "nsISupports.h"
#include "nsISupportsImpl.h"
#include "nsISupportsPriority.h"
#include "nsIThread.h"
#include "nsITimer.h"
#include "nsIURI.h"
+#include "nsIURIMutator.h"
#include "nsNetUtil.h"
#include "nsPrintfCString.h"
#include "nsQueryObject.h"
#include "nsRefPtrHashtable.h"
#include "nsStreamUtils.h"
#include "nsString.h"
#include "nsStringStream.h"
#include "nsThreadPool.h"
@@ -4194,40 +4195,41 @@ GetDatabaseFileURL(nsIFile* aDatabaseFil
}
nsCOMPtr<nsIFileProtocolHandler> fileHandler(
do_QueryInterface(protocolHandler, &rv));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
- nsCOMPtr<nsIURI> uri;
- rv = fileHandler->NewFileURI(aDatabaseFile, getter_AddRefs(uri));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(uri);
- MOZ_ASSERT(fileUrl);
+ nsCOMPtr<nsIURIMutator> mutator;
+ rv = fileHandler->NewFileURIMutator(aDatabaseFile, getter_AddRefs(mutator));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsCOMPtr<nsIFileURL> fileUrl;
nsAutoCString type;
PersistenceTypeToText(aPersistenceType, type);
nsAutoCString telemetryFilenameClause;
if (aTelemetryId) {
telemetryFilenameClause.AssignLiteral("&telemetryFilename=indexedDB-");
telemetryFilenameClause.AppendInt(aTelemetryId);
telemetryFilenameClause.AppendLiteral(".sqlite");
}
- rv = fileUrl->SetQuery(NS_LITERAL_CSTRING("persistenceType=") + type +
- NS_LITERAL_CSTRING("&group=") + aGroup +
- NS_LITERAL_CSTRING("&origin=") + aOrigin +
- NS_LITERAL_CSTRING("&cache=private") +
- telemetryFilenameClause);
+ rv = NS_MutateURI(mutator)
+ .SetQuery(NS_LITERAL_CSTRING("persistenceType=") + type +
+ NS_LITERAL_CSTRING("&group=") + aGroup +
+ NS_LITERAL_CSTRING("&origin=") + aOrigin +
+ NS_LITERAL_CSTRING("&cache=private") +
+ telemetryFilenameClause)
+ .Finalize(fileUrl);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
fileUrl.forget(aResult);
return NS_OK;
}
--- a/dom/url/URLMainThread.cpp
+++ b/dom/url/URLMainThread.cpp
@@ -451,17 +451,19 @@ URLMainThread::SetHash(const nsAString&
.Finalize(mURI);
}
void
URLMainThread::SetSearchInternal(const nsAString& aSearch, ErrorResult& aRv)
{
// Ignore failures to be compatible with NS4.
- mURI->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
+ Unused << NS_MutateURI(mURI)
+ .SetQuery(NS_ConvertUTF16toUTF8(aSearch))
+ .Finalize(mURI);
}
nsIURI*
URLMainThread::GetURI() const
{
MOZ_ASSERT(NS_IsMainThread());
return mURI;
}
--- a/dom/url/URLWorker.cpp
+++ b/dom/url/URLWorker.cpp
@@ -5,16 +5,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "URLWorker.h"
#include "mozilla/dom/Blob.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRunnable.h"
#include "mozilla/dom/WorkerScope.h"
+#include "mozilla/Unused.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsStandardURL.h"
#include "nsURLHelper.h"
namespace mozilla {
using net::nsStandardURL;
@@ -1163,17 +1164,19 @@ URLWorker::SetHash(const nsAString& aHas
MOZ_ASSERT(!runnable->Failed());
}
void
URLWorker::SetSearchInternal(const nsAString& aSearch, ErrorResult& aRv)
{
if (mStdURL) {
// URLMainThread ignores failures here.
- mStdURL->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
+ Unused << NS_MutateURI(mStdURL)
+ .SetQuery(NS_ConvertUTF16toUTF8(aSearch))
+ .Finalize(mStdURL);
return;
}
MOZ_ASSERT(mURLProxy);
RefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterSearch,
aSearch, mURLProxy);
--- a/modules/libjar/nsJARURI.cpp
+++ b/modules/libjar/nsJARURI.cpp
@@ -673,17 +673,19 @@ NS_IMETHODIMP
nsJARURI::GetQuery(nsACString& query)
{
return mJAREntry->GetQuery(query);
}
NS_IMETHODIMP
nsJARURI::SetQuery(const nsACString& query)
{
- return mJAREntry->SetQuery(query);
+ return NS_MutateURI(mJAREntry)
+ .SetQuery(query)
+ .Finalize(mJAREntry);
}
NS_IMETHODIMP
nsJARURI::SetQueryWithEncoding(const nsACString& query,
const Encoding* encoding)
{
return NS_MutateURI(mJAREntry)
.SetQueryWithEncoding(query, encoding)
--- a/netwerk/protocol/file/nsFileChannel.cpp
+++ b/netwerk/protocol/file/nsFileChannel.cpp
@@ -18,21 +18,24 @@
#include "nsIFileStreams.h"
#include "nsFileProtocolHandler.h"
#include "nsProxyRelease.h"
#include "nsAutoPtr.h"
#include "nsIContentPolicy.h"
#include "nsContentUtils.h"
#include "nsIFileURL.h"
+#include "nsIURIMutator.h"
#include "nsIFile.h"
#include "nsIMIMEService.h"
#include "prio.h"
#include <algorithm>
+#include "mozilla/Unused.h"
+
using namespace mozilla;
using namespace mozilla::net;
//-----------------------------------------------------------------------------
class nsFileCopyEvent : public Runnable {
public:
nsFileCopyEvent(nsIOutputStream* dest, nsIInputStream* source, int64_t len)
@@ -296,17 +299,19 @@ nsFileChannel::Init()
#endif
NS_SUCCEEDED(NS_NewFileURI(getter_AddRefs(targetURI),
resolvedFile, nullptr))) {
// Make an effort to match up the query strings.
nsCOMPtr<nsIURL> origURL = do_QueryInterface(mFileURI);
nsCOMPtr<nsIURL> targetURL = do_QueryInterface(targetURI);
nsAutoCString queryString;
if (origURL && targetURL && NS_SUCCEEDED(origURL->GetQuery(queryString))) {
- targetURL->SetQuery(queryString);
+ Unused << NS_MutateURI(targetURI)
+ .SetQuery(queryString)
+ .Finalize(targetURI);
}
SetURI(targetURI);
SetOriginalURI(mFileURI);
mLoadInfo->SetResultPrincipalURI(targetURI);
} else {
SetURI(mFileURI);
}
--- a/netwerk/protocol/file/nsFileProtocolHandler.cpp
+++ b/netwerk/protocol/file/nsFileProtocolHandler.cpp
@@ -252,16 +252,44 @@ nsFileProtocolHandler::NewFileURI(nsIFil
// charset by the SetFile method.
rv = url->SetFile(file);
if (NS_FAILED(rv)) return rv;
return CallQueryInterface(url, result);
}
NS_IMETHODIMP
+nsFileProtocolHandler::NewFileURIMutator(nsIFile *aFile, nsIURIMutator **aResult)
+{
+ NS_ENSURE_ARG_POINTER(aFile);
+ nsresult rv;
+
+ nsCOMPtr<nsIURI> url = new nsStandardURL(true);
+ nsCOMPtr<nsIURIMutator> mutator;
+ rv = url->Mutate(getter_AddRefs(mutator));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ nsCOMPtr<nsIFileURLMutator> fileMutator = do_QueryInterface(mutator, &rv);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ // NOTE: the origin charset is assigned the value of the platform
+ // charset by the SetFile method.
+ rv = fileMutator->SetFile(aFile);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ mutator.forget(aResult);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsFileProtocolHandler::GetURLSpecFromFile(nsIFile *file, nsACString &result)
{
NS_ENSURE_ARG_POINTER(file);
return net_GetURLSpecFromFile(file, result);
}
NS_IMETHODIMP
nsFileProtocolHandler::GetURLSpecFromActualFile(nsIFile *file,
--- a/netwerk/protocol/file/nsFileProtocolHandler.h
+++ b/netwerk/protocol/file/nsFileProtocolHandler.h
@@ -4,16 +4,18 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsFileProtocolHandler_h__
#define nsFileProtocolHandler_h__
#include "nsIFileProtocolHandler.h"
#include "nsWeakReference.h"
+class nsIURIMutator;
+
class nsFileProtocolHandler : public nsIFileProtocolHandler
, public nsSupportsWeakReference
{
virtual ~nsFileProtocolHandler() {}
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIPROTOCOLHANDLER
--- a/netwerk/protocol/file/nsIFileProtocolHandler.idl
+++ b/netwerk/protocol/file/nsIFileProtocolHandler.idl
@@ -1,29 +1,40 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/. */
#include "nsIProtocolHandler.idl"
interface nsIFile;
+interface nsIURIMutator;
[scriptable, uuid(1fb25bd5-4354-4dcd-8d97-621b7b3ed2e4)]
interface nsIFileProtocolHandler : nsIProtocolHandler
{
/**
* This method constructs a new file URI
*
* @param aFile nsIFile
* @return reference to a new nsIURI object
*/
nsIURI newFileURI(in nsIFile aFile);
/**
+ * This method constructs a new file URI, and returns a URI mutator
+ * that has not yet been finalized, allowing the URI to be changed without
+ * being cloned.
+ *
+ * @param aFile nsIFile
+ * @return reference to a new nsIURIMutator object
+ */
+ nsIURIMutator newFileURIMutator(in nsIFile file);
+
+ /**
* Converts the nsIFile to the corresponding URL string. NOTE: under
* some platforms this is a lossy conversion (e.g., Mac Carbon build).
* If the nsIFile is a local file, then the result will be a file://
* URL string.
*
* The resulting string may contain URL-escaped characters.
* NOTE: Callers should use getURLSpecFromActualFile or
* getURLSpecFromDirFile if possible, for performance reasons.
--- a/netwerk/test/unit/test_URIs.js
+++ b/netwerk/test/unit/test_URIs.js
@@ -522,17 +522,17 @@ function do_test_mutate_ref(aTest, aSuff
// 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",
- "host", "port", "query"];
+ "host", "port"];
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
@@ -623,17 +623,17 @@ function do_test_mutate_ref(aTest, aSuff
// 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",
- "host", "port", "query"];
+ "host", "port"];
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
@@ -77,26 +77,26 @@ add_test(function test_setQuery()
/* And one that's nonempty but shorter than "foo" */
["http://example.com/?f#bar", "http://example.com/?foo#bar"],
["http://example.com/?f", "http://example.com/?foo"],
].map(pairToURLs);
for (var [provided, target] of pairs) {
symmetricEquality(false, provided, target);
- provided.query = "foo";
+ provided = provided.mutate().setQuery("foo").finalize().QueryInterface(Ci.nsIURL);
Assert.equal(provided.spec, target.spec);
symmetricEquality(true, provided, target);
}
[provided, target] =
["http://example.com/#", "http://example.com/?foo#bar"].map(stringToURL);
symmetricEquality(false, provided, target);
- provided.query = "foo";
+ provided = provided.mutate().setQuery("foo").finalize().QueryInterface(Ci.nsIURL);
symmetricEquality(false, provided, target);
var newProvided = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService)
.newURI("#bar", null, provided)
.QueryInterface(Components.interfaces.nsIURL);
Assert.equal(newProvided.spec, target.spec);
@@ -297,32 +297,32 @@ 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",
- "host",
- "query"];
+ "host"];
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: "setUsername", qi: Ci.nsIURIMutator },
{ method: "setPassword", qi: Ci.nsIURIMutator },
{ method: "setFilePath", qi: Ci.nsIURIMutator },
{ method: "setHostPort", qi: Ci.nsIURIMutator },
{ method: "setUserPass", qi: Ci.nsIURIMutator },
{ method: "setPathQueryRef", qi: Ci.nsIURIMutator },
+ { method: "setQuery", qi: Ci.nsIURIMutator },
{ method: "setRef", 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(),
@@ -337,17 +337,17 @@ add_test(function test_filterWhitespace(
{
var url = stringToURL(" \r\n\th\nt\rt\tp://ex\r\n\tample.com/path\r\n\t/\r\n\tto the/fil\r\n\te.e\r\n\txt?que\r\n\try#ha\r\n\tsh \r\n\t ");
Assert.equal(url.spec, "http://example.com/path/to%20the/file.ext?query#hash");
// These setters should escape \r\n\t, not filter them.
var url = stringToURL("http://test.com/path?query#hash");
url = url.mutate().setFilePath("pa\r\n\tth").finalize();
Assert.equal(url.spec, "http://test.com/pa%0D%0A%09th?query#hash");
- url.query = "qu\r\n\tery";
+ url = url.mutate().setQuery("qu\r\n\tery").finalize();
Assert.equal(url.spec, "http://test.com/pa%0D%0A%09th?qu%0D%0A%09ery#hash");
url = url.mutate().setRef("ha\r\n\tsh").finalize();
Assert.equal(url.spec, "http://test.com/pa%0D%0A%09th?qu%0D%0A%09ery#ha%0D%0A%09sh");
url = url.mutate().QueryInterface(Ci.nsIURLMutator).setFileName("fi\r\n\tle.name").finalize();
Assert.equal(url.spec, "http://test.com/fi%0D%0A%09le.name?qu%0D%0A%09ery#ha%0D%0A%09sh");
run_next_test();
});
@@ -406,17 +406,17 @@ add_test(function test_encode_C0_and_spa
var url = stringToURL("http://example.com/pa" + String.fromCharCode(i) + "th?qu" + String.fromCharCode(i) +"ery#ha" + String.fromCharCode(i) + "sh");
Assert.equal(url.spec, "http://example.com/pa%" + toHex(i) + "th?qu%" + toHex(i) + "ery#ha%" + toHex(i) + "sh");
}
// Additionally, we need to check the setters.
var url = stringToURL("http://example.com/path?query#hash");
url = url.mutate().setFilePath("pa\0th").finalize();
Assert.equal(url.spec, "http://example.com/pa%00th?query#hash");
- url.query = "qu\0ery";
+ url = url.mutate().setQuery("qu\0ery").finalize();
Assert.equal(url.spec, "http://example.com/pa%00th?qu%00ery#hash");
url = url.mutate().setRef("ha\0sh").finalize();
Assert.equal(url.spec, "http://example.com/pa%00th?qu%00ery#ha%00sh");
url = url.mutate().QueryInterface(Ci.nsIURLMutator).setFileName("fi\0le.name").finalize();
Assert.equal(url.spec, "http://example.com/fi%00le.name?qu%00ery#ha%00sh");
run_next_test();
});
--- a/services/sync/modules/addonutils.js
+++ b/services/sync/modules/addonutils.js
@@ -267,17 +267,19 @@ AddonUtilsInternal.prototype = {
function rewrite(param) {
if (param.indexOf("src=") == 0) {
return "src=sync";
}
return param;
});
- addon.sourceURI.query = params.join("&");
+ addon.sourceURI = addon.sourceURI.mutate()
+ .setQuery(params.join("&"))
+ .finalize();
}
if (!toInstall.length) {
return ourResult;
}
const installPromises = [];
// Start all the installs asynchronously. They will report back to us
--- a/services/sync/modules/record.js
+++ b/services/sync/modules/record.js
@@ -636,17 +636,19 @@ Collection.prototype = {
}
if (this._commit) {
args.push("commit=true");
}
if (this._offset) {
args.push("offset=" + encodeURIComponent(this._offset));
}
- this.uri.query = (args.length > 0) ? "?" + args.join("&") : "";
+ this.uri = this.uri.mutate()
+ .setQuery((args.length > 0) ? "?" + args.join("&") : "")
+ .finalize();
},
// get full items
get full() { return this._full; },
set full(value) {
this._full = value;
this._rebuildURL();
},
--- a/services/sync/tests/unit/test_resource.js
+++ b/services/sync/tests/unit/test_resource.js
@@ -507,17 +507,20 @@ add_test(function test_uri_construction(
args.push("sort=" + 1234);
let query = "?" + args.join("&");
let uri1 = CommonUtils.makeURI("http://foo/" + query)
.QueryInterface(Ci.nsIURL);
let uri2 = CommonUtils.makeURI("http://foo/")
.QueryInterface(Ci.nsIURL);
- uri2.query = query;
+ uri2 = uri2.mutate()
+ .setQuery(query)
+ .finalize()
+ .QueryInterface(Ci.nsIURL);
Assert.equal(uri1.query, uri2.query);
run_next_test();
});
/**
* End of tests that rely on a single HTTP server.
* All tests after this point must begin and end their own.
--- a/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm
+++ b/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm
@@ -68,17 +68,19 @@ var ImageCropper = {
let fileName = file.leafName + "-" + aScreen.width + "x" + aScreen.height;
let croppedFile = FileUtils.getFile("ProfD", ["lwtheme", fileName]);
// If we have a local file that is not in progress, return it.
if (croppedFile.exists() && !(croppedFile.path in this._inProgress)) {
let fileURI = Services.io.newFileURI(croppedFile);
// Copy the query part to avoid wrong caching.
- fileURI.QueryInterface(Ci.nsIURL).query = uri.query;
+ fileURI = fileURI.mutate()
+ .setQuery(uri.query)
+ .finalize();
return fileURI.spec;
}
// Crop the given image in the background.
this._crop(uri, croppedFile, aScreen, aOrigin);
// Return the original image while we're waiting for the cropped version
// to be written to disk.