Bug 1743653 - tests for external protocol handler redirection, r=nika CLOSED TREE

Differential Revision: https://phabricator.services.mozilla.com/D132528
This commit is contained in:
Gijs Kruitbosch 2022-03-29 08:25:46 -04:00
Родитель 6a5e277a4c
Коммит 857af4fe02
4 изменённых файлов: 212 добавлений и 7 удалений

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

@ -97,6 +97,9 @@ support-files =
support-files =
redirect_helper.sjs
[browser_protocol_ask_dialog_permission.js]
support-files =
redirect_helper.sjs
script_redirect.html
[browser_protocolhandler_loop.js]
[browser_remember_download_option.js]
[browser_txt_download_save_as.js]

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

@ -7,6 +7,11 @@ let gHandlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(
Ci.nsIHandlerService
);
const ROOT_PATH = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content/",
""
);
// Testing multiple protocol / origin combinations takes long on debug.
requestLongerTimeout(3);
@ -120,6 +125,9 @@ async function triggerOpenProto(
useNullPrincipal = false,
useExtensionPrincipal = false,
omitTriggeringPrincipal = false,
useJSRedirect = false,
serverRedirect = "",
linkToRedirect = false,
} = {}
) {
let uri = `${scheme}://test`;
@ -172,6 +180,65 @@ async function triggerOpenProto(
return;
}
if (useJSRedirect) {
let innerParams = new URLSearchParams();
innerParams.set("uri", uri);
let params = new URLSearchParams();
params.set(
"uri",
"https://example.com/" +
ROOT_PATH +
"script_redirect.html?" +
innerParams.toString()
);
uri =
"https://example.org/" +
ROOT_PATH +
"script_redirect.html?" +
params.toString();
BrowserTestUtils.loadURI(browser, uri);
return;
}
if (serverRedirect) {
let innerParams = new URLSearchParams();
innerParams.set("uri", uri);
innerParams.set("redirectType", serverRedirect);
let params = new URLSearchParams();
params.set(
"uri",
"https://example.com/" +
ROOT_PATH +
"redirect_helper.sjs?" +
innerParams.toString()
);
uri =
"https://example.org/" +
ROOT_PATH +
"redirect_helper.sjs?" +
params.toString();
BrowserTestUtils.loadURI(browser, uri);
return;
}
if (linkToRedirect) {
let params = new URLSearchParams();
params.set("uri", uri);
uri =
"https://example.com/" +
ROOT_PATH +
"redirect_helper.sjs?" +
params.toString();
await ContentTask.spawn(browser, { uri }, args => {
let textLink = content.document.createElement("a");
textLink.href = args.uri;
textLink.textContent = "click me";
content.document.body.appendChild(textLink);
textLink.click();
});
return;
}
info("Loading uri: " + uri);
browser.loadURI(uri, { triggeringPrincipal });
}
@ -229,6 +296,7 @@ async function testOpenProto(
let {
hasCheckbox,
checkboxOrigin,
hasChangeApp,
chooserIsNext,
actionCheckbox,
@ -254,6 +322,7 @@ async function testOpenProto(
await testCheckbox(dialogEl, dialogType, {
hasCheckbox,
actionCheckbox,
checkboxOrigin,
});
// Check the button label depending on whether we would show the chooser
@ -311,7 +380,11 @@ async function testOpenProto(
}
// Clean up test extension if needed.
await testExtension?.unload();
if (testExtension) {
await testExtension.unload();
// Don't try to unload it again later!
testExtension = null;
}
}
/**
@ -330,7 +403,7 @@ async function testOpenProto(
async function testCheckbox(
dialogEl,
dialogType,
{ hasCheckbox, hasCheckboxState = false, actionCheckbox }
{ hasCheckbox, hasCheckboxState = false, actionCheckbox, checkboxOrigin }
) {
let checkbox = dialogEl.ownerDocument.getElementById("remember");
if (typeof hasCheckbox == "boolean") {
@ -358,6 +431,14 @@ async function testCheckbox(
is(checkbox.checked, hasCheckboxState, "Dialog checkbox has correct state");
}
if (checkboxOrigin) {
let doc = dialogEl.ownerDocument;
let hostFromLabel = doc.l10n.getAttributes(
doc.getElementById("remember-label")
).args.host;
is(hostFromLabel, checkboxOrigin, "Checkbox should be for correct domain.");
}
if (typeof actionCheckbox == "boolean") {
checkbox.click();
}
@ -768,3 +849,103 @@ add_task(async function test_extension_principal() {
});
});
});
/**
* Test that we use the redirect principal for the dialog when applicable.
*/
add_task(async function test_redirect_principal() {
let scheme = TEST_PROTOS[0];
await BrowserTestUtils.withNewTab("about:blank", async browser => {
await testOpenProto(browser, scheme, {
loadOptions: {
serverRedirect: "location",
},
permDialogOptions: {
checkboxOrigin: ORIGIN1,
chooserIsNext: true,
hasCheckbox: true,
actionConfirm: false, // Cancel dialog
},
});
});
});
/**
* Test that we use the redirect principal for the dialog for refresh headers.
*/
add_task(async function test_redirect_principal() {
let scheme = TEST_PROTOS[0];
await BrowserTestUtils.withNewTab("about:blank", async browser => {
await testOpenProto(browser, scheme, {
loadOptions: {
serverRedirect: "refresh",
},
permDialogOptions: {
checkboxOrigin: ORIGIN1,
chooserIsNext: true,
hasCheckbox: true,
actionConfirm: false, // Cancel dialog
},
});
});
});
/**
* Test that we use the redirect principal for the dialog for meta refreshes.
*/
add_task(async function test_redirect_principal() {
let scheme = TEST_PROTOS[0];
await BrowserTestUtils.withNewTab("about:blank", async browser => {
await testOpenProto(browser, scheme, {
loadOptions: {
serverRedirect: "meta-refresh",
},
permDialogOptions: {
checkboxOrigin: ORIGIN1,
chooserIsNext: true,
hasCheckbox: true,
actionConfirm: false, // Cancel dialog
},
});
});
});
/**
* Test that we use the redirect principal for the dialog for JS redirects.
*/
add_task(async function test_redirect_principal_js() {
let scheme = TEST_PROTOS[0];
await BrowserTestUtils.withNewTab("about:blank", async browser => {
await testOpenProto(browser, scheme, {
loadOptions: {
useJSRedirect: true,
},
permDialogOptions: {
checkboxOrigin: ORIGIN1,
chooserIsNext: true,
hasCheckbox: true,
actionConfirm: false, // Cancel dialog
},
});
});
});
/**
* Test that we use the redirect principal for the dialog for link clicks.
*/
add_task(async function test_redirect_principal_links() {
let scheme = TEST_PROTOS[0];
await BrowserTestUtils.withNewTab("about:blank", async browser => {
await testOpenProto(browser, scheme, {
loadOptions: {
linkToRedirect: true,
},
permDialogOptions: {
checkboxOrigin: ORIGIN1,
chooserIsNext: true,
hasCheckbox: true,
actionConfirm: false, // Cancel dialog
},
});
});
});

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

@ -6,9 +6,25 @@
Cu.importGlobalProperties(["URLSearchParams"]);
function handleRequest(request, response) {
response.setStatusLine(request.httpVersion, 302, "Moved Temporarily");
response.setHeader(
"Location",
new URLSearchParams(request.queryString).get("uri")
);
let params = new URLSearchParams(request.queryString);
let uri = params.get("uri");
let redirectType = params.get("redirectType") || "location";
switch (redirectType) {
case "refresh":
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Refresh", "0; url=" + uri);
break;
case "meta-refresh":
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "text/html");
response.write(`<meta http-equiv="refresh" content="0; url=${uri}">`);
break;
case "location":
// fall through
default:
response.setStatusLine(request.httpVersion, 302, "Moved Temporarily");
response.setHeader("Location", uri);
}
}

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

@ -0,0 +1,5 @@
<script>
let params = new URL(document.location).searchParams;
let uri = params.get("uri");
document.location = uri;
</script>