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 : 9907f7c54f43851ba1a956a5d278d301013204d2
This commit is contained in:
Mike Hommey 2017-09-30 08:49:28 +09:00
Родитель e29fd6597a
Коммит 155c57e385
2 изменённых файлов: 27 добавлений и 1 удалений

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

@ -425,7 +425,27 @@ SubstitutingProtocolHandler::ResolveURI(nsIURI *uri, nsACString &result)
rv = baseURI->GetSpec(result);
} else {
// 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);
}

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

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