Bug 1960237 - Only offer "Add Search Engine" for forms with an explicit action attribute. r=search-reviewers,scunnane
Differential Revision: https://phabricator.services.mozilla.com/D247775
This commit is contained in:
committed by
mbeier@mozilla.com
parent
69dee15e68
commit
094ffaecef
@@ -241,7 +241,7 @@ export class ContextMenuChild extends JSWindowActorChild {
|
||||
!node.name ||
|
||||
(method != "POST" && method != "GET") ||
|
||||
node.form.enctype != "application/x-www-form-urlencoded" ||
|
||||
formData.entries().some(([k, v]) => !k && typeof v != "string")
|
||||
formData.values().some(v => typeof v != "string")
|
||||
) {
|
||||
// This should never happen since these conditions are checked in
|
||||
// `isTargetASearchEngineField`.
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { SpellCheckHelper } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/InlineSpellChecker.sys.mjs"
|
||||
);
|
||||
|
||||
ChromeUtils.defineLazyGetter(this, "UrlbarTestUtils", () => {
|
||||
const { UrlbarTestUtils: module } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/UrlbarTestUtils.sys.mjs"
|
||||
@@ -66,12 +70,6 @@ const URL_UTF_8 =
|
||||
const URL_WINDOWS1252 =
|
||||
"https://example.org/browser/browser/components/search/test/browser/test_windows1252.html";
|
||||
|
||||
add_setup(async function () {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.urlbar.update2.engineAliasRefresh", true]],
|
||||
});
|
||||
});
|
||||
|
||||
async function addEngine(browser, selector, name, alias) {
|
||||
let contextMenu = document.getElementById("contentAreaContextMenu");
|
||||
let addEngineItem = document.getElementById("context-add-engine");
|
||||
@@ -164,7 +162,27 @@ async function navigateToCharset(charset) {
|
||||
}
|
||||
}
|
||||
|
||||
add_task(async function () {
|
||||
function postDataToString(postData) {
|
||||
if (!postData) {
|
||||
return undefined;
|
||||
}
|
||||
let binaryStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(
|
||||
Ci.nsIBinaryInputStream
|
||||
);
|
||||
binaryStream.setInputStream(postData.data);
|
||||
|
||||
return binaryStream
|
||||
.readBytes(binaryStream.available())
|
||||
.replace("searchTerms", "%s");
|
||||
}
|
||||
|
||||
add_setup(async function () {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.urlbar.update2.engineAliasRefresh", true]],
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function testAddingEngines() {
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
@@ -187,7 +205,7 @@ add_task(async function () {
|
||||
"Submission URI is correct"
|
||||
);
|
||||
Assert.equal(
|
||||
postDataToString(submission.postData),
|
||||
SearchTestUtils.getPostDataString(submission),
|
||||
args.expectedPost,
|
||||
"Submission post data is correct."
|
||||
);
|
||||
@@ -202,16 +220,56 @@ add_task(async function () {
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
function postDataToString(postData) {
|
||||
if (!postData) {
|
||||
return undefined;
|
||||
}
|
||||
let binaryStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(
|
||||
Ci.nsIBinaryInputStream
|
||||
);
|
||||
binaryStream.setInputStream(postData.data);
|
||||
add_task(async function testSearchFieldDetection() {
|
||||
let form = document.createElement("form");
|
||||
form.method = "GET";
|
||||
form.action = "/";
|
||||
|
||||
return binaryStream
|
||||
.readBytes(binaryStream.available())
|
||||
.replace("searchTerms", "%s");
|
||||
}
|
||||
let input = document.createElement("input");
|
||||
input.type = "search";
|
||||
input.name = "q";
|
||||
form.appendChild(input);
|
||||
|
||||
let isSearchField = SpellCheckHelper.isTargetASearchEngineField(
|
||||
input,
|
||||
window
|
||||
);
|
||||
Assert.equal(isSearchField, true, "Is search field initially");
|
||||
|
||||
// We test mostly non search fields here since valid search fields
|
||||
// are already tested in testAddingEngines.
|
||||
delete form.removeAttribute("action");
|
||||
isSearchField = SpellCheckHelper.isTargetASearchEngineField(input, window);
|
||||
Assert.equal(isSearchField, false, "Missing action means no search field");
|
||||
|
||||
form.action = "/";
|
||||
|
||||
form.method = "dialog";
|
||||
isSearchField = SpellCheckHelper.isTargetASearchEngineField(input, window);
|
||||
Assert.equal(isSearchField, false, "Method=dialog means no search field");
|
||||
|
||||
form.method = "POST";
|
||||
|
||||
delete input.removeAttribute("name");
|
||||
isSearchField = SpellCheckHelper.isTargetASearchEngineField(input, window);
|
||||
Assert.equal(isSearchField, false, "Missing name means no search field");
|
||||
|
||||
input.name = "q";
|
||||
|
||||
input.type = "url";
|
||||
isSearchField = SpellCheckHelper.isTargetASearchEngineField(input, window);
|
||||
Assert.equal(isSearchField, false, "Url input means no search field");
|
||||
|
||||
input.type = "text";
|
||||
|
||||
let fileInput = document.createElement("input");
|
||||
fileInput.type = "file";
|
||||
fileInput.name = "file-input";
|
||||
form.appendChild(fileInput);
|
||||
isSearchField = SpellCheckHelper.isTargetASearchEngineField(input, window);
|
||||
Assert.equal(isSearchField, false, "File input means no search field");
|
||||
|
||||
fileInput.remove();
|
||||
isSearchField = SpellCheckHelper.isTargetASearchEngineField(input, window);
|
||||
Assert.equal(isSearchField, true, "Is search field again");
|
||||
});
|
||||
|
||||
@@ -761,6 +761,26 @@ class _SearchTestUtils {
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts post data string from an nsISearchSubmission.
|
||||
* If there is no post data, returns null.
|
||||
*
|
||||
* @param {?nsISearchSubmission} submission
|
||||
* @returns {?string}
|
||||
*/
|
||||
getPostDataString(submission) {
|
||||
if (!submission.postData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let binaryStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(
|
||||
Ci.nsIBinaryInputStream
|
||||
);
|
||||
binaryStream.setInputStream(submission.postData.data);
|
||||
|
||||
return binaryStream.readBytes(binaryStream.available());
|
||||
}
|
||||
}
|
||||
|
||||
export const SearchTestUtils = new _SearchTestUtils();
|
||||
|
||||
@@ -110,23 +110,9 @@ add_task(async function test_encoding_of_spaces() {
|
||||
let submission = engine.getSubmission("f o o");
|
||||
Assert.equal(submission.uri.spec, "https://example.com/user");
|
||||
Assert.equal(
|
||||
postDataToString(submission.postData),
|
||||
SearchTestUtils.getPostDataString(submission),
|
||||
"q=f+o+o",
|
||||
"Encodes spaces in body as +."
|
||||
);
|
||||
await Services.search.removeEngine(engine);
|
||||
});
|
||||
|
||||
function postDataToString(postData) {
|
||||
if (!postData) {
|
||||
return undefined;
|
||||
}
|
||||
let binaryStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(
|
||||
Ci.nsIBinaryInputStream
|
||||
);
|
||||
binaryStream.setInputStream(postData.data);
|
||||
|
||||
return binaryStream
|
||||
.readBytes(binaryStream.available())
|
||||
.replace("searchTerms", "%s");
|
||||
}
|
||||
|
||||
@@ -473,21 +473,39 @@ export var SpellCheckHelper = {
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether the element is counted as a search engine field.
|
||||
*
|
||||
* @param {HTMLInputElement} aNode
|
||||
* The input to check.
|
||||
* @param {Window} window
|
||||
* The element's window.
|
||||
* @returns {boolean}
|
||||
* Whether it should count as a search engine field.
|
||||
*/
|
||||
isTargetASearchEngineField(aNode, window) {
|
||||
if (!window.HTMLInputElement.isInstance(aNode)) {
|
||||
if (
|
||||
!window.HTMLInputElement.isInstance(aNode) ||
|
||||
(aNode.type != "text" && aNode.type != "search") ||
|
||||
aNode.readOnly ||
|
||||
!aNode.name ||
|
||||
!aNode.form
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let form = aNode.form;
|
||||
if (!form || aNode.type == "password" || !aNode.name) {
|
||||
return false;
|
||||
}
|
||||
let method = form.method.toUpperCase();
|
||||
|
||||
return (
|
||||
// Forms without an explicit action often don't work, see Bug 1960237.
|
||||
form.hasAttribute("action") &&
|
||||
// The only other method is dialog.
|
||||
(method == "GET" || method == "POST") &&
|
||||
// SearchEngine objects currently only support urlencoded requests.
|
||||
form.enctype == "application/x-www-form-urlencoded" &&
|
||||
new FormData(form).entries().every(([k, v]) => k && typeof v == "string")
|
||||
// Don't allow forms with file inputs.
|
||||
new FormData(form).values().every(v => typeof v == "string")
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user