Bug 1405174 - Fix resolution of resource: URLs when the target of the substitution doesn't end with a /. r=valentin

When for some reason the target of a resource: substitution doesn't end
with a / (which can happen when e.g. building a FileURI with a path
that doesn't exist), relative path resolution of the resource URLs end
up rooted under the parent of the non-existing directory.

e.g
  resource://foo/bar is substituted with /path/for/bar if
  resource://foo/ is registered for file:///path/for/foo (instead of
  file:///path/for/foo/)

--HG--
extra : rebase_source : b59dae0337a707a96adfc1c89c27235a856ec58e
This commit is contained in:
Mike Hommey 2017-09-30 08:49:28 +09:00
Родитель 5057df5497
Коммит d43f368c0d
2 изменённых файлов: 27 добавлений и 1 удалений

Просмотреть файл

@ -425,7 +425,27 @@ SubstitutingProtocolHandler::ResolveURI(nsIURI *uri, nsACString &result)
rv = baseURI->GetSpec(result); rv = baseURI->GetSpec(result);
} else { } else {
// Make sure we always resolve the path as file-relative to our target URI. // Make sure we always resolve the path as file-relative to our target URI.
path.Insert('.', 0); // When the baseURI is a nsIFileURL, and the directory it points to doesn't
// exist, it doesn't end with a /. In that case, a file-relative resolution
// is going to pick something in the parent directory, so we resolve using
// an absolute path derived from the full path in that case.
nsCOMPtr<nsIFileURL> baseDir = do_QueryInterface(baseURI);
if (baseDir) {
nsAutoCString basePath;
rv = baseURI->GetFilePath(basePath);
if (NS_SUCCEEDED(rv) && !StringEndsWith(basePath, NS_LITERAL_CSTRING("/"))) {
// Cf. the assertion above, path already starts with a /, so prefixing
// with a string that doesn't end with one will leave us wit the right
// amount of /.
path.Insert(basePath, 0);
} else {
// Allow to fall through below.
baseDir = nullptr;
}
}
if (!baseDir) {
path.Insert('.', 0);
}
rv = baseURI->Resolve(path, result); rv = baseURI->Resolve(path, result);
} }

Просмотреть файл

@ -94,9 +94,14 @@ function run_test() {
let rootFile = Services.dirsvc.get("GreD", Ci.nsIFile); let rootFile = Services.dirsvc.get("GreD", Ci.nsIFile);
let rootURI = Services.io.newFileURI(rootFile); let rootURI = Services.io.newFileURI(rootFile);
rootFile.append("directory-that-does-not-exist");
let inexistentURI = Services.io.newFileURI(rootFile);
resProto.setSubstitution("res-test", rootURI); resProto.setSubstitution("res-test", rootURI);
resProto.setSubstitution("res-inexistent", inexistentURI);
do_register_cleanup(() => { do_register_cleanup(() => {
resProto.setSubstitution("res-test", null); resProto.setSubstitution("res-test", null);
resProto.setSubstitution("res-inexistent", null);
}); });
let baseRoot = resProto.resolveURI(Services.io.newURI("resource:///")); let baseRoot = resProto.resolveURI(Services.io.newURI("resource:///"));
@ -104,6 +109,7 @@ function run_test() {
for (var spec of specs) { for (var spec of specs) {
check_safe_resolution(spec, rootURI.spec); check_safe_resolution(spec, rootURI.spec);
check_safe_resolution(spec.replace("res-test", "res-inexistent"), inexistentURI.spec);
check_safe_resolution(spec.replace("res-test", ""), baseRoot); check_safe_resolution(spec.replace("res-test", ""), baseRoot);
check_safe_resolution(spec.replace("res-test", "gre"), greRoot); check_safe_resolution(spec.replace("res-test", "gre"), greRoot);
} }